ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-08-05 05:53:33
Exec Total Coverage
Lines: 98 7652 1.3%
Functions: 1 196 0.5%
Branches: 14 6421 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "zq/zquestdat.h"
15 #include "zq/zq_tiles.h"
16 #include "zq/zquest.h"
17 #include "tiles.h"
18 #include "zq/zq_misc.h"
19 #include "zq/zq_class.h"
20 #include "base/zsys.h"
21 #include "base/colors.h"
22 #include "qst.h"
23 #include "gui/jwin.h"
24 #include <base/new_menu.h>
25 #include "base/jwinfsel.h"
26 #include "zc/zc_custom.h"
27 #include "zq/questReport.h"
28 #include "dialog/info.h"
29 #include "dialog/scaletile.h"
30 #include "dialog/rotatetile.h"
31 #include "dialog/alert.h"
32 #include "drawing.h"
33 #include "colorname.h"
34 #include "zq/render.h"
35 #include "zinfo.h"
36 #include <fmt/format.h>
37 #include <functional>
38 #include "zq/moveinfo.h"
39 using std::set;
40
41 extern zcmodule moduledata;
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 9 size_and_pos ok_button(302,562,71,21);
1230 9 size_and_pos cancel_button(376,562,71,21);
1231 9 size_and_pos edit_button(550,562,86,21);
1232 9 size_and_pos hlcbox(742,392,16,16);
1233 9 size_and_pos hov_prev(742,338,50,50);
1234 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 9 size_and_pos fg_prev(648,316,50,50);
1237 9 size_and_pos bg_prev(648+30,316+30,50,50);
1238 9 size_and_pos zoomtile(124,32,16,16,32,32);
1239 9 size_and_pos prev_til_1(648,31,96,96);
1240 9 size_and_pos prev_til_2(752,31,96,96);
1241 9 size_and_pos prev_til_3(648,135,96,96);
1242 9 size_and_pos prev_til_4(752,135,96,96);
1243 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1244 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1245 9 size_and_pos color_info(4,189,1,1,116,8);
1246 9 size_and_pos color_info_btn(24,189,96,21);
1247 9 size_and_pos tool_btns(22,29,2,4,39,39);
1248 9 size_and_pos x_btn(890,5,15,13);
1249 9 size_and_pos info_btn(872,5,15,13);
1250 9 size_and_pos hidegrid_cbox(124,552,16,16);
1251 9 size_and_pos quartgrid_cbox(124,572,16,16);
1252 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1253 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1254 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1255
1256 int32_t c1=1;
1257 int32_t c2=0;
1258 int32_t floating_tile = -1;
1259 int32_t tool = t_pen;
1260 int32_t old_tool = -1;
1261 int32_t tool_cur = -1;
1262 int32_t select_mode = 0;
1263 int32_t drawing=0;
1264
1265 bool qgrid_tool(int tool)
1266 {
1267 switch(tool)
1268 {
1269 case t_pen:
1270 case t_fill:
1271 case t_recolor:
1272 case t_wand:
1273 return true;
1274 }
1275 return false;
1276 }
1277
1278 void set_tool_sprite(int tool, int type)
1279 {
1280 int spr = ZQM_NORMAL;
1281 switch(tool)
1282 {
1283 case t_pen: spr = ZQM_SWORD; break;
1284 case t_fill: spr = ZQM_POTION; break;
1285 case t_recolor: spr = ZQM_WAND; break;
1286 case t_eyedropper: spr = ZQM_LENS; break;
1287 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1288 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1289 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1290 }
1291 MouseSprite::set(spr);
1292 }
1293 void update_tool_cursor()
1294 {
1295 int32_t temp_mouse_x=gui_mouse_x();
1296 int32_t temp_mouse_y=gui_mouse_y();
1297
1298 int32_t type=0;
1299
1300 if(has_selection())
1301 {
1302 switch(tool)
1303 {
1304 case t_select:
1305 case t_wand:
1306 type+=select_mode;
1307 break;
1308 }
1309 }
1310
1311 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1312 {
1313 if(tool_cur==-1)
1314 set_tool_sprite(tool,type);
1315
1316 tool_cur=tool;
1317 }
1318 else if(tool_cur != -1)
1319 {
1320 MouseSprite::set(ZQM_NORMAL);
1321 tool_cur = -1;
1322 }
1323 }
1324
1325 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1326 {
1327 PALETTE tpal;
1328 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1329 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1330 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1331
1332 if(!create_tbar)
1333 {
1334 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1335 }
1336 else
1337 {
1338 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1339 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1340 }
1341
1342 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1343
1344 clear_to_color(preview_bmp, 0);
1345
1346 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1347 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1348 puttile16(preview_bmp,tile,0,0,cs,flip);
1349 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1350
1351 clear_to_color(preview_bmp, 0);
1352 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1353 overtile16(preview_bmp,tile,0,0,cs,flip);
1354 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1355 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1356
1357 unpack_tile(newtilebuf, tile, 0, true);
1358 if(floating_sel)
1359 for(auto q = 0; q < 256; ++q)
1360 if(floatsel[q])
1361 unpackbuf[q] = floatsel[q];
1362 byte tmptile[256];
1363 byte *tmpptr = tmptile;
1364 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1365 pack_tile(newtilebuf,unpackbuf,tile);
1366 clear_to_color(preview_bmp, 0);
1367
1368 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1369 puttile16(preview_bmp,tile,0,0,cs,flip);
1370 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1371
1372 clear_to_color(preview_bmp, 0);
1373 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1374 overtile16(preview_bmp,tile,0,0,cs,flip);
1375 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1376
1377 //Color info
1378 {
1379 auto fh = color_info.yscale = text_height(font);
1380 int y = color_info.y;
1381 int rx = color_info.x+color_info.xscale;
1382 color_info.h = 1;
1383 if(showcolortip)
1384 {
1385 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1386 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1387 auto str = get_tile_colornames(tile,cs);
1388 size_t pos = 0;
1389 char buf[512] = {0};
1390 char cbuf[16] = {0};
1391 while(pos < str.size())
1392 {
1393 y += fh;
1394 if(y+fh > zq_screen_h)
1395 break; //Out of space!
1396 auto endpos = str.find_first_of('\n',pos);
1397
1398 if(endpos == std::string::npos)
1399 {
1400 strcpy(buf,str.substr(pos).c_str());
1401 pos = str.size();
1402 }
1403 else
1404 {
1405 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1406 pos = endpos+1;
1407 }
1408 //Ensure the name fits horizontally
1409 if(text_length(font,buf) > color_info.xscale)
1410 {
1411 size_t pos = 0;
1412 for(; buf[pos]; ++pos)
1413 {
1414 if(buf[pos] == ':')
1415 {
1416 strcpy(cbuf, buf+pos);
1417 buf[pos] = 0;
1418 break;
1419 }
1420 }
1421 size_t clen = text_length(font,cbuf);
1422 size_t dotlen = text_length(font,"..");
1423
1424 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1425 buf[--pos] = 0;
1426 while(buf[pos] == ' ')
1427 buf[pos] = 0;
1428 strcat(buf,"..");
1429 strcat(buf,cbuf);
1430 }
1431 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1432 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1433 ++color_info.h;
1434 }
1435 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1436 }
1437 else
1438 {
1439 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1440 "Show Colors",vc(1),vc(14),0,true);
1441 }
1442 }
1443
1444 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1445
1446 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1447 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1448
1449 if(floating_sel)
1450 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1451 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1452 if(newtilebuf[tile].format==tf8Bit)
1453 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1454 else
1455 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1456
1457 PALETTE temppal;
1458
1459 //palette and mouse
1460 switch(newtilebuf[tile].format)
1461 {
1462 case tf4Bit:
1463 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1464 get_palette(temppal);
1465
1466 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1467 {
1468 size_and_pos const& s = cpalette_4.subsquare(i);
1469 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1470 }
1471
1472 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1473 break;
1474
1475 case tf8Bit:
1476 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1477
1478 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1479 {
1480 size_and_pos const& s = cpalette_8.subsquare(i);
1481 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1482 }
1483
1484 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1485 break;
1486 }
1487
1488 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1489 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1490 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1491
1492 if(c2==0)
1493 {
1494 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1495 }
1496
1497 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1498 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1499 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1500
1501 if(c1==0)
1502 {
1503 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1504 }
1505
1506 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1507 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1508 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1509 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1510 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1511
1512 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1513 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1514
1515 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1516 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1517
1518 bool qgrd = show_quartgrid && qgrid_tool(tool);
1519 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1520 for(int q = 0; q < REFL_MAX; ++q)
1521 {
1522 auto& sqr = reflbtn_grid.subsquare(q);
1523 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1524 }
1525 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1526 for(int q = 0; q < XMODE_MAX; ++q)
1527 {
1528 auto& sqr = xmodebtn_grid.subsquare(q);
1529 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1530 }
1531 for(int q = 0; q < BGMODE_MAX; ++q)
1532 {
1533 auto& sqr = bgmodebtn_grid.subsquare(q);
1534 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1535 }
1536
1537 //tool buttons
1538 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1539 {
1540 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1541 int col = toolbtn%tool_btns.w;
1542 int row = toolbtn/tool_btns.w;
1543
1544 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1545 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1546 }
1547
1548 //coordinates
1549 {
1550 auto mx = gui_mouse_x();
1551 auto my = gui_mouse_y();
1552 int32_t ind = zoomtile.rectind(mx,my);
1553 int32_t temp_x=ind%zoomtile.w;
1554 int32_t temp_y=ind/zoomtile.w;
1555 int color = -1;
1556
1557 bool is8b = newtilebuf[tile].format > tf4Bit;
1558 if(ind > -1)
1559 {
1560 char xbuf[16];
1561 sprintf(xbuf, "x: %d", temp_x);
1562 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1563 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1564 unpack_tile(newtilebuf, tile, 0, false);
1565 byte *si = unpackbuf;
1566 si+=ind;
1567 color = *si;
1568 }
1569 else if(fg_prev.rect(mx,my))
1570 color = c1;
1571 else if(bg_prev.rect(mx,my))
1572 color = c2;
1573 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1574 if(color > -1)
1575 {
1576 get_palette(tpal);
1577 char separator = ' ';
1578 char buf[512] = {0};
1579
1580 int realcol = color+(is8b?0:CSET(cs));
1581 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1582 auto& c = tpal[realcol];
1583
1584 if(tthighlight)
1585 {
1586 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1587 size_and_pos const& csqr = mainsqr.subsquare(color);
1588
1589 int hlcol = getHighlightColor(tpal[realcol]);
1590 int hlthick = 4;
1591 int extraborder = is8b ? 8 : 0;
1592 int borderthick = hlthick+extraborder;
1593
1594 if(is8b)
1595 {
1596 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1597 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1598 }
1599 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1600 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1601 if(xcolor)
1602 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1603 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1604 }
1605
1606 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1607 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1608
1609 strcpy(buf, get_color_name(realcol, is8b).c_str());
1610 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1611
1612 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1613 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1614
1615 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1616 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1617 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1618 if(xcolor)
1619 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1620 }
1621 }
1622
1623 custom_vsync();
1624 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1625 update_tool_cursor();
1626 SCRFIX();
1627 }
1628
1629 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1630 {
1631 unfloat_selection();
1632 if(tile>tile2)
1633 {
1634 zc_swap(tile, tile2);
1635 }
1636
1637 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1638 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1639
1640 int32_t start=tile;
1641 int32_t end=tile2;
1642
1643 // Might have top-right and bottom-left corners selected...
1644 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1645 {
1646 start=tile-(TILECOL(tile)-TILECOL(tile2));
1647 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1648 }
1649
1650 for(int32_t temptile=start; temptile<=end; temptile++)
1651 {
1652 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1653 {
1654 unpack_tile(newtilebuf, temptile, 0, true);
1655
1656 if(flip&1)
1657 {
1658 for(int32_t y=0; y<16; y++)
1659 {
1660 for(int32_t x=0; x<8; x++)
1661 {
1662 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1663 }
1664 }
1665 }
1666
1667 if(flip&2)
1668 {
1669 for(int32_t y=0; y<8; y++)
1670 {
1671 for(int32_t x=0; x<16; x++)
1672 {
1673 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1674 }
1675 }
1676 }
1677
1678 pack_tile(newtilebuf,unpackbuf,temptile);
1679 }
1680 }
1681 }
1682
1683 void rotate_tile(int32_t tile, bool backward)
1684 {
1685 unfloat_selection();
1686 unpack_tile(newtilebuf, tile, 0, true);
1687 byte tempunpackbuf[256];
1688 byte tempx, tempy;
1689
1690 for(tempx=0; tempx<16; tempx++)
1691 {
1692 for(tempy=0; tempy<16; tempy++)
1693 {
1694 if(!backward)
1695 {
1696 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1697 }
1698 else
1699 {
1700 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1701 }
1702 }
1703 }
1704
1705 pack_tile(newtilebuf,tempunpackbuf,tile);
1706 }
1707
1708 static int32_t undocount=128;
1709 byte undotile[256];
1710
1711 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1712 {
1713 byte buf[256];
1714
1715 for(int32_t i=0; i<undocount; i++)
1716 {
1717 newtilebuf[tile].data[i]=undotile[i];
1718 }
1719
1720 if(!(horizontal||vertical))
1721 {
1722 return;
1723 }
1724
1725 unpack_tile(newtilebuf, tile, 0, true);
1726
1727 for(int32_t i=0; i<256; i++)
1728 {
1729 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1730 buf[shift_ind] = unpackbuf[i];
1731 }
1732
1733 if(clear)
1734 {
1735 for(int32_t r=0; r<abs(vertical); r++)
1736 {
1737 for(int32_t c=0; c<16; c++)
1738 {
1739 buf[(vertical>0?r:15-r)*16+c]=0;
1740 }
1741 }
1742
1743 for(int32_t r=0; r<16; r++)
1744 {
1745 for(int32_t c=0; c<abs(horizontal); c++)
1746 {
1747 buf[r*16+(horizontal>0?c:15-c)]=0;
1748 }
1749 }
1750 }
1751
1752 pack_tile(newtilebuf,buf,tile);
1753 }
1754
1755 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1756 {
1757 byte buf[256];
1758
1759 if(!(horizontal||vertical))
1760 {
1761 return;
1762 }
1763
1764 memset(buf,0,256);
1765
1766 for(int32_t i=0; i<256; i++)
1767 {
1768 if(is_in_selection(i%16,i/16))
1769 {
1770 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1771 buf[shift_ind] = floatsel[i];
1772 }
1773 }
1774
1775 memcpy(floatsel,buf,256);
1776 }
1777
1778 void float_selection(int32_t tile, bool clear)
1779 {
1780 if(floating_sel) return;
1781 floating_sel = true;
1782 floating_tile = tile;
1783
1784 unpack_tile(newtilebuf, tile, 0, true);
1785
1786 for(auto q = 0; q < 256; ++q)
1787 {
1788 if(is_in_selection(q%16,q/16))
1789 {
1790 floatsel[q] = unpackbuf[q];
1791 unpackbuf[q] = clear ? 0 : c2;
1792 }
1793 else floatsel[q] = 0;
1794 }
1795
1796 pack_tile(newtilebuf,unpackbuf,tile);
1797 }
1798
1799 void unfloat_selection()
1800 {
1801 if(!floating_sel) return;
1802 floating_sel = false;
1803
1804 unpack_tile(newtilebuf, floating_tile, 0, true);
1805
1806 for(auto q = 0; q < 256; ++q)
1807 {
1808 if(floatsel[q])
1809 {
1810 unpackbuf[q] = floatsel[q];
1811 }
1812 }
1813
1814 pack_tile(newtilebuf,unpackbuf,floating_tile);
1815 floating_tile = -1;
1816 }
1817
1818 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1819 {
1820 if(floating_sel)
1821 {
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(ignore_transparent && floatsel[q]==0)
1825 continue;
1826 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1827 }
1828 return;
1829 }
1830
1831 byte buf[256];
1832 unpack_tile(newtilebuf, tile, 0, true);
1833
1834 for(int32_t i=0; i<256; i++)
1835 {
1836 buf[i]=unpackbuf[i];
1837
1838 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1839 continue;
1840
1841 if(ignore_transparent)
1842 {
1843 if(buf[i]==0)
1844 continue;
1845
1846 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1847 }
1848 else // Don't ignore transparent
1849 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1850 }
1851
1852 pack_tile(newtilebuf,buf,tile);
1853 }
1854
1855 void clear_selection_grid()
1856 {
1857 unfloat_selection();
1858 for(int32_t x=0; x<18; ++x)
1859 {
1860 for(int32_t y=0; y<18; ++y)
1861 {
1862 selection_grid[x][y]=0;
1863 }
1864 }
1865 }
1866
1867 void invert_selection_grid()
1868 {
1869 unfloat_selection();
1870 for(int32_t x=1; x<17; ++x)
1871 {
1872 for(int32_t y=1; y<17; ++y)
1873 {
1874 selection_grid[x][y]=selection_grid[x][y]?0:1;
1875 }
1876 }
1877 }
1878
1879 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1880 {
1881 byte local_grid[16][16];
1882 memset(local_grid, 0, sizeof(local_grid));
1883 for(auto x = 0; x < 16; ++x)
1884 {
1885 for(auto y = 0; y < 16; ++y)
1886 {
1887 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1888 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1889 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1890 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1891 }
1892 }
1893 for(auto x = 0; x < 16; ++x)
1894 {
1895 for(auto y = 0; y < 16; ++y)
1896 {
1897 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1898 }
1899 }
1900 }
1901
1902 void show_edit_tile_help()
1903 {
1904 InfoDialog("Help: Tile Editor", "Hotkeys:"
1905 "\nF1: This Help Dialog"
1906 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1907 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1908 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1909 "\nH/V: Flip | (Shift+)R: Rotate"
1910 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1911 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1912 "\nF12: Screenshot (whole screen)"
1913 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1914 "\nWhen not on Select tools, hold to swap:"
1915 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1916 }
1917
1918 static int move_origin_x=-1, move_origin_y=-1;
1919 static int prev_x=-1, prev_y=-1;
1920 bool __pixel_draw(int x, int y, int tile, int flip)
1921 {
1922 bool ret = false;
1923 switch(tool)
1924 {
1925 case t_pen:
1926 if(flip&1) x=15-x;
1927
1928 if(flip&2) y=15-y;
1929
1930 if(is_in_selection(x,y))
1931 {
1932 if(floating_sel)
1933 {
1934 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1935 }
1936 else
1937 {
1938 unpack_tile(newtilebuf, tile, 0, false);
1939 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1940 pack_tile(newtilebuf, unpackbuf,tile);
1941 }
1942 }
1943 break;
1944
1945 case t_fill:
1946 if(is_in_selection(x,y))
1947 {
1948 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1949 ret = true;
1950 }
1951 break;
1952
1953 case t_recolor:
1954 if(is_in_selection(x,y))
1955 {
1956 if(floating_sel)
1957 {
1958 tf_u = floatsel[(y<<4)+x];
1959 for(int32_t i=0; i<256; i++)
1960 {
1961 if(is_in_selection(i&15,i>>4))
1962 {
1963 if(floatsel[i]==tf_u)
1964 {
1965 floatsel[i]=(drawing==1)?c1:c2;
1966 }
1967 }
1968 }
1969 }
1970 else
1971 {
1972 unpack_tile(newtilebuf, tile, 0, false);
1973 tf_u = unpackbuf[(y<<4)+x];
1974 if(tf_u != ((drawing==1)?c1:c2))
1975 {
1976 for(int32_t i=0; i<256; i++)
1977 {
1978 if(is_in_selection(i&15,i>>4))
1979 {
1980 if(unpackbuf[i]==tf_u)
1981 {
1982 unpackbuf[i]=(drawing==1)?c1:c2;
1983 }
1984 }
1985 }
1986
1987 pack_tile(newtilebuf, unpackbuf,tile);
1988 }
1989 }
1990 ret = true;
1991 }
1992 break;
1993
1994 case t_eyedropper:
1995 if(floating_sel)
1996 memcpy(unpackbuf, floatsel, 256);
1997 else unpack_tile(newtilebuf, tile, 0, false);
1998
1999 if(gui_mouse_b()&1)
2000 {
2001 c1=unpackbuf[((y<<4)+x)];
2002 }
2003
2004 if(gui_mouse_b()&2)
2005 {
2006 c2=unpackbuf[((y<<4)+x)];
2007 }
2008 break;
2009
2010 case t_move:
2011 if((prev_x!=x)||(prev_y!=y))
2012 {
2013 if(has_selection())
2014 {
2015 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2016 wrap_sel_tile(y-prev_y, x-prev_x);
2017 shift_selection_grid(x-prev_x, y-prev_y);
2018 }
2019 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2020 prev_x=x;
2021 prev_y=y;
2022 }
2023 break;
2024
2025 case t_select:
2026 unfloat_selection();
2027 if(flip&1) x=15-x;
2028
2029 if(flip&2) y=15-y;
2030
2031 if(selecting_x1==-1||selecting_y1==-1)
2032 {
2033 selecting_x1=x;
2034 selecting_y1=y;
2035 }
2036 else
2037 {
2038 selecting_x2=x;
2039 selecting_y2=y;
2040 }
2041 break;
2042
2043 case t_wand:
2044 unfloat_selection();
2045 if(flip&1) x=15-x;
2046
2047 if(flip&2) y=15-y;
2048
2049 switch(select_mode)
2050 {
2051 case 0:
2052 clear_selection_grid();
2053 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2054 break;
2055
2056 case 1:
2057 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2058 break;
2059
2060 case 2:
2061 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2062 break;
2063
2064 case 3:
2065 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2066 break;
2067 }
2068
2069 ret = true;
2070 break;
2071 }
2072 return ret;
2073 }
2074 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2075 {
2076 popup_zqdialog_start();
2077 FONT* oldfont = font;
2078 font = get_custom_font(CFONT_DLG);
2079 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2080 status_info.yscale = text_height(font);
2081 status_info.y = 308-(status_info.h*status_info.yscale);
2082 hover_info.yscale = status_info.yscale;
2083 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2084 go();
2085 undocount = tilesize(newtilebuf[tile].format);
2086 clear_selection_grid();
2087 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2088
2089 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2090 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2091
2092 PALETTE tpal;
2093 byte oldtile[256];
2094
2095 memset(&tpal, 0, sizeof(PALETTE));
2096 memset(oldtile, 0, 256);
2097
2098 for(int32_t i=0; i<undocount; i++)
2099 {
2100 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2101 }
2102 byte undoselgrid[16][16];
2103 for(auto x = 0; x < 16; ++x)
2104 for(auto y = 0; y < 16; ++y)
2105 undoselgrid[x][y] = selection_grid[x+1][y+1];
2106 for(auto q = 0; q < 256; ++q)
2107 {
2108 floatsel[q] = 0;
2109 undofloatsel[q] = 0;
2110 floating_sel = false;
2111 undo_is_floatsel = false;
2112 }
2113
2114 int32_t tile_x=-1, tile_y=-1;
2115 int32_t temp_x=-1, temp_y=-1;
2116 bool bdown=false;
2117 int32_t done=0;
2118 drawing=0;
2119 tool_cur = -1;
2120
2121 get_palette(tpal);
2122
2123 if(newtilebuf[tile].format==tf4Bit)
2124 {
2125 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2126 }
2127 else
2128 {
2129 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2130 }
2131
2132 custom_vsync();
2133 zc_set_palette(tpal);
2134 draw_edit_scr(tile,flip,cs,oldtile, true);
2135
2136 while(gui_mouse_b())
2137 {
2138 /* do nothing */
2139 rest(1);
2140 }
2141
2142 move_origin_x=-1;
2143 move_origin_y=-1;
2144 prev_x=-1;
2145 prev_y=-1;
2146
2147
2148
2149 byte selection_pattern_source[8][8]=
2150 {
2151 {1, 1, 1, 1, 0, 0, 0, 0},
2152 {1, 1, 1, 0, 0, 0, 0, 1},
2153 {1, 1, 0, 0, 0, 0, 1, 1},
2154 {1, 0, 0, 0, 0, 1, 1, 1},
2155 {0, 0, 0, 0, 1, 1, 1, 1},
2156 {0, 0, 0, 1, 1, 1, 1, 0},
2157 {0, 0, 1, 1, 1, 1, 0, 0},
2158 {0, 1, 1, 1, 1, 0, 0, 0},
2159 };
2160
2161 byte selecting_pattern_source[8][8]=
2162 {
2163 {1, 1, 0, 0, 0, 0, 1, 1},
2164 {1, 0, 0, 0, 0, 1, 1, 1},
2165 {0, 0, 0, 0, 1, 1, 1, 1},
2166 {0, 0, 0, 1, 1, 1, 1, 0},
2167 {0, 0, 1, 1, 1, 1, 0, 0},
2168 {0, 1, 1, 1, 1, 0, 0, 0},
2169 {1, 1, 1, 1, 0, 0, 0, 0},
2170 {1, 1, 1, 0, 0, 0, 0, 1},
2171 };
2172
2173 byte intersection_pattern_source[8][8]=
2174 {
2175 {0, 0, 1, 1, 0, 0, 1, 1},
2176 {0, 1, 1, 0, 0, 1, 1, 0},
2177 {1, 1, 0, 0, 1, 1, 0, 0},
2178 {1, 0, 0, 1, 1, 0, 0, 1},
2179 {0, 0, 1, 1, 0, 0, 1, 1},
2180 {0, 1, 1, 0, 0, 1, 1, 0},
2181 {1, 1, 0, 0, 1, 1, 0, 0},
2182 {1, 0, 0, 1, 1, 0, 0, 1},
2183 };
2184
2185 selection_pattern=create_bitmap_ex(8, 8, 8);
2186
2187 for(int32_t x=0; x<8; ++x)
2188 {
2189 for(int32_t y=0; y<8; ++y)
2190 {
2191 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2192 }
2193 }
2194
2195 selecting_pattern=create_bitmap_ex(8, 8, 8);
2196
2197 for(int32_t x=0; x<8; ++x)
2198 {
2199 for(int32_t y=0; y<8; ++y)
2200 {
2201 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2202 }
2203 }
2204
2205 intersection_pattern=create_bitmap_ex(8, 8, 8);
2206
2207 for(int32_t x=0; x<8; ++x)
2208 {
2209 for(int32_t y=0; y<8; ++y)
2210 {
2211 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2212 }
2213 }
2214
2215 do
2216 {
2217 HANDLE_CLOSE_ZQDLG();
2218 if(exiting_program) break;
2219 int32_t temp_mouse_x=gui_mouse_x();
2220 int32_t temp_mouse_y=gui_mouse_y();
2221 rest(4);
2222 bool redraw=false;
2223 bool did_wand_select=false;
2224
2225 if(keypressed())
2226 {
2227 bool ctrl = CHECK_CTRL_CMD;
2228 int k = readkey()>>8;
2229 switch(k)
2230 {
2231 case KEY_F1:
2232 show_edit_tile_help();
2233 break;
2234 case KEY_ENTER_PAD:
2235 case KEY_ENTER:
2236 if(floating_sel)
2237 unfloat_selection();
2238 else done=2;
2239 break;
2240
2241 case KEY_ESC:
2242 if(floating_sel)
2243 unfloat_selection();
2244 else if(has_selection())
2245 clear_selection_grid();
2246 else done=1;
2247 break;
2248
2249 case KEY_DEL:
2250 {
2251 unpack_tile(newtilebuf, tile, 0, false);
2252 bool all = CHECK_CTRL_CMD || !has_selection();
2253 bool canDel = false;
2254 if(all)
2255 {
2256 //Check all
2257 for(auto q = 0; q < 256; ++q)
2258 if(unpackbuf[q])
2259 {
2260 canDel = true;
2261 break;
2262 }
2263 }
2264 else
2265 {
2266 //Check selection
2267 for(auto x = 0; x < 16; ++x)
2268 for(auto y = 0; y < 16; ++y)
2269 if(is_in_selection(x,y))
2270 if(unpackbuf[(y<<4)+x])
2271 {
2272 canDel = true;
2273 break;
2274 }
2275 }
2276 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2277
2278 for(int32_t i=0; i<undocount; i++)
2279 {
2280 undotile[i]=newtilebuf[tile].data[i];
2281 }
2282 for(auto x = 0; x < 16; ++x)
2283 for(auto y = 0; y < 16; ++y)
2284 undoselgrid[x][y] = selection_grid[x+1][y+1];
2285 for(auto q = 0; q < 256; ++q)
2286 undofloatsel[q] = floatsel[q];
2287 undo_is_floatsel = floating_sel;
2288
2289 if(CHECK_CTRL_CMD || !has_selection())
2290 {
2291 //Delete all
2292 for(auto q = 0; q < 256; ++q)
2293 {
2294 unpackbuf[q] = 0;
2295 floatsel[q] = 0;
2296 }
2297 }
2298 else
2299 {
2300 //Delete selection
2301 for(auto x = 0; x < 16; ++x)
2302 for(auto y = 0; y < 16; ++y)
2303 {
2304 if(floating_sel)
2305 {
2306 floatsel[x+(y<<4)] = 0;
2307 }
2308 else if(is_in_selection(x,y))
2309 {
2310 unpackbuf[(y<<4)+x] = 0;
2311 }
2312 }
2313 }
2314 pack_tile(newtilebuf, unpackbuf, tile);
2315 redraw=true;
2316 }
2317 break;
2318
2319 case KEY_A:
2320 clear_selection_grid();
2321 invert_selection_grid();
2322 redraw=true;
2323 break;
2324
2325 case KEY_D:
2326 clear_selection_grid();
2327 redraw=true;
2328 break;
2329
2330 case KEY_I:
2331 invert_selection_grid();
2332 redraw=true;
2333 break;
2334
2335 case KEY_H:
2336 flip^=1;
2337 normalize(tile,tile,0,flip);
2338 flip=0;
2339 redraw=true;
2340 break;
2341
2342 case KEY_V:
2343 flip^=2;
2344 normalize(tile,tile,0,flip);
2345 flip=0;
2346 redraw=true;
2347 break;
2348
2349 case KEY_F12:
2350 onSnapshot();
2351 break;
2352
2353 case KEY_R:
2354 {
2355 //if(CHECK_CTRL_CMD))
2356 // {
2357 //do_recolor(tile); redraw=true; saved=false;
2358 // }
2359 //else
2360 // {
2361 go_tiles();
2362 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2363 redraw=true;
2364 saved=false;
2365 break;
2366 }
2367
2368 case KEY_EQUALS:
2369 case KEY_PLUS_PAD:
2370 {
2371 if(CHECK_CTRL_CMD ||
2372 key[KEY_ALT] || key[KEY_ALTGR])
2373 {
2374 for(int32_t i=0; i<undocount; i++)
2375 undotile[i]=newtilebuf[tile].data[i];
2376 for(auto x = 0; x < 16; ++x)
2377 for(auto y = 0; y < 16; ++y)
2378 undoselgrid[x][y] = selection_grid[x+1][y+1];
2379 for(auto q = 0; q < 256; ++q)
2380 undofloatsel[q] = floatsel[q];
2381 undo_is_floatsel = floating_sel;
2382
2383 if(key[KEY_ALT] || key[KEY_ALTGR])
2384 shift_tile_colors(tile, 16, false);
2385 else
2386 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2387 }
2388 else
2389 cs = (cs<13) ? cs+1:0;
2390
2391 redraw=true;
2392 break;
2393 }
2394
2395 case KEY_MINUS:
2396 case KEY_MINUS_PAD:
2397 {
2398 if(CHECK_CTRL_CMD ||
2399 key[KEY_ALT] || key[KEY_ALTGR])
2400 {
2401 for(int32_t i=0; i<undocount; i++)
2402 undotile[i]=newtilebuf[tile].data[i];
2403 for(auto x = 0; x < 16; ++x)
2404 for(auto y = 0; y < 16; ++y)
2405 undoselgrid[x][y] = selection_grid[x+1][y+1];
2406 for(auto q = 0; q < 256; ++q)
2407 undofloatsel[q] = floatsel[q];
2408 undo_is_floatsel = floating_sel;
2409
2410 if(key[KEY_ALT] || key[KEY_ALTGR])
2411 shift_tile_colors(tile, -16, false);
2412 else
2413 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2414 }
2415 else
2416 cs = (cs>0) ? cs-1:13;
2417
2418 redraw=true;
2419 break;
2420 }
2421
2422 case KEY_SPACE:
2423 gridmode=(gridmode+1)%gm_max;
2424 redraw=true;
2425 break;
2426
2427 case KEY_Z:
2428 if(!ctrl)
2429 break;
2430 //Ctrl+Z == undo
2431 [[fallthrough]];
2432 case KEY_U:
2433 for(int32_t i=0; i<undocount; i++)
2434 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2435
2436 for(auto x = 0; x < 16; ++x)
2437 for(auto y = 0; y < 16; ++y)
2438 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2439
2440 for(auto q = 0; q < 256; ++q)
2441 zc_swap(undofloatsel[q], floatsel[q]);
2442 zc_swap(undo_is_floatsel, floating_sel);
2443
2444 redraw=true;
2445 break;
2446
2447 case KEY_S:
2448 if(CHECK_CTRL_CMD)
2449 {
2450 for(int32_t i=0; i<undocount; i++)
2451 {
2452 undotile[i]=newtilebuf[tile].data[i];
2453 }
2454 for(auto x = 0; x < 16; ++x)
2455 for(auto y = 0; y < 16; ++y)
2456 undoselgrid[x][y] = selection_grid[x+1][y+1];
2457 for(auto q = 0; q < 256; ++q)
2458 undofloatsel[q] = floatsel[q];
2459 undo_is_floatsel = floating_sel;
2460
2461 unpack_tile(newtilebuf, tile, 0, false);
2462
2463 if(has_selection())
2464 {
2465 for(int32_t i=0; i<256; i++)
2466 {
2467 if(!is_in_selection(i%16,i/16))
2468 continue;
2469 if(unpackbuf[i]==c1)
2470 {
2471 unpackbuf[i]=c2;
2472 }
2473 else if(unpackbuf[i]==c2)
2474 {
2475 unpackbuf[i]=c1;
2476 }
2477 if(floating_sel)
2478 {
2479 if(floatsel[i]==c1)
2480 {
2481 floatsel[i]=c2;
2482 }
2483 else if(floatsel[i]==c2)
2484 {
2485 floatsel[i]=c1;
2486 }
2487 }
2488 }
2489 }
2490 else
2491 {
2492 for(int32_t i=0; i<256; i++)
2493 {
2494 if(unpackbuf[i]==c1)
2495 {
2496 unpackbuf[i]=c2;
2497 }
2498 else if(unpackbuf[i]==c2)
2499 {
2500 unpackbuf[i]=c1;
2501 }
2502 }
2503 }
2504
2505 pack_tile(newtilebuf, unpackbuf,tile);
2506 }
2507
2508 zc_swap(c1,c2);
2509 redraw=true;
2510 break;
2511
2512 case KEY_UP:
2513 if(CHECK_CTRL_CMD)
2514 {
2515 unfloat_selection();
2516 tile=zc_max(0,tile-TILES_PER_ROW);
2517 undocount = tilesize(newtilebuf[tile].format);
2518
2519 for(int32_t i=0; i<undocount; i++)
2520 {
2521 undotile[i]=newtilebuf[tile].data[i];
2522 oldtile[i]=undotile[i];
2523 }
2524
2525 redraw=true;
2526 }
2527 else
2528 {
2529 for(int32_t i=0; i<undocount; i++)
2530 {
2531 undotile[i]=newtilebuf[tile].data[i];
2532 }
2533 for(auto x = 0; x < 16; ++x)
2534 for(auto y = 0; y < 16; ++y)
2535 undoselgrid[x][y] = selection_grid[x+1][y+1];
2536 for(auto q = 0; q < 256; ++q)
2537 undofloatsel[q] = floatsel[q];
2538 undo_is_floatsel = floating_sel;
2539 if(has_selection())
2540 {
2541 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2542 wrap_sel_tile(-1, 0);
2543 shift_selection_grid(0, -1);
2544 }
2545 else wrap_tile(tile, -1, 0, false);
2546 redraw=true;
2547 }
2548 break;
2549
2550 case KEY_DOWN:
2551 if(CHECK_CTRL_CMD)
2552 {
2553 unfloat_selection();
2554 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2555 undocount = tilesize(newtilebuf[tile].format);
2556
2557 for(int32_t i=0; i<undocount; i++)
2558 {
2559 undotile[i]=newtilebuf[tile].data[i];
2560 oldtile[i]=undotile[i];
2561 }
2562
2563 redraw=true;
2564 }
2565 else
2566 {
2567 for(int32_t i=0; i<undocount; i++)
2568 {
2569 undotile[i]=newtilebuf[tile].data[i];
2570 }
2571 for(auto x = 0; x < 16; ++x)
2572 for(auto y = 0; y < 16; ++y)
2573 undoselgrid[x][y] = selection_grid[x+1][y+1];
2574 for(auto q = 0; q < 256; ++q)
2575 undofloatsel[q] = floatsel[q];
2576 undo_is_floatsel = floating_sel;
2577 if(has_selection())
2578 {
2579 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2580 wrap_sel_tile(1, 0);
2581 shift_selection_grid(0, 1);
2582 }
2583 else wrap_tile(tile, 1, 0, false);
2584 redraw=true;
2585 }
2586 break;
2587
2588 case KEY_LEFT:
2589 if(CHECK_CTRL_CMD)
2590 {
2591 unfloat_selection();
2592 tile=zc_max(0,tile-1);
2593 undocount = tilesize(newtilebuf[tile].format);
2594
2595 for(int32_t i=0; i<undocount; i++)
2596 {
2597 undotile[i]=newtilebuf[tile].data[i];
2598 oldtile[i]=undotile[i];
2599 }
2600
2601 redraw=true;
2602 }
2603 else
2604 {
2605 for(int32_t i=0; i<undocount; i++)
2606 {
2607 undotile[i]=newtilebuf[tile].data[i];
2608 }
2609 for(auto x = 0; x < 16; ++x)
2610 for(auto y = 0; y < 16; ++y)
2611 undoselgrid[x][y] = selection_grid[x+1][y+1];
2612 for(auto q = 0; q < 256; ++q)
2613 undofloatsel[q] = floatsel[q];
2614 undo_is_floatsel = floating_sel;
2615 if(has_selection())
2616 {
2617 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2618 wrap_sel_tile(0, -1);
2619 shift_selection_grid(-1, 0);
2620 }
2621 else wrap_tile(tile, 0, -1, false);
2622 redraw=true;
2623 }
2624 break;
2625
2626 case KEY_RIGHT:
2627 if(CHECK_CTRL_CMD)
2628 {
2629 unfloat_selection();
2630 tile=zc_min(tile+1, NEWMAXTILES-1);
2631 undocount = tilesize(newtilebuf[tile].format);
2632
2633 for(int32_t i=0; i<undocount; i++)
2634 {
2635 undotile[i]=newtilebuf[tile].data[i];
2636 oldtile[i]=undotile[i];
2637 }
2638
2639 redraw=true;
2640 }
2641 else
2642 {
2643 for(int32_t i=0; i<undocount; i++)
2644 {
2645 undotile[i]=newtilebuf[tile].data[i];
2646 }
2647 for(auto x = 0; x < 16; ++x)
2648 for(auto y = 0; y < 16; ++y)
2649 undoselgrid[x][y] = selection_grid[x+1][y+1];
2650 for(auto q = 0; q < 256; ++q)
2651 undofloatsel[q] = floatsel[q];
2652 undo_is_floatsel = floating_sel;
2653 if(has_selection())
2654 {
2655 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2656 wrap_sel_tile(0, 1);
2657 shift_selection_grid(1, 0);
2658 }
2659 else wrap_tile(tile, 0, 1, false);
2660 redraw=true;
2661 }
2662 break;
2663 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2664 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2665 case KEY_8: case KEY_9:
2666 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2667 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2668 case KEY_8_PAD: case KEY_9_PAD:
2669 {
2670 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2671 if(unsigned(t) < t_max)
2672 {
2673 if(old_tool != -1)
2674 old_tool = t;
2675 else tool = t;
2676 }
2677 break;
2678 }
2679 case KEY_TAB:
2680 {
2681 if(key_shifts & KB_CTRL_FLAG)
2682 {
2683 xmode = (xmode+1)%XMODE_MAX;
2684 if(!xmode)
2685 bgmode = (bgmode+1)%BGMODE_MAX;
2686 }
2687 else if(key_shifts & KB_SHIFT_FLAG)
2688 hide_grid = !hide_grid;
2689 else show_quartgrid = !show_quartgrid;
2690 redraw = true;
2691 break;
2692 }
2693 }
2694 clear_keybuf();
2695 }
2696
2697 if(!gui_mouse_b())
2698 {
2699 if(is_selecting())
2700 {
2701 unfloat_selection();
2702 int32_t x1=zc_min(selecting_x1,selecting_x2);
2703 int32_t x2=zc_max(selecting_x1,selecting_x2);
2704 int32_t y1=zc_min(selecting_y1,selecting_y2);
2705 int32_t y2=zc_max(selecting_y1,selecting_y2);
2706
2707 if(select_mode==0)
2708 {
2709 clear_selection_grid();
2710 }
2711
2712 for(int32_t x=x1; x<=x2; ++x)
2713 {
2714 for(int32_t y=y1; y<=y2; ++y)
2715 {
2716 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2717 }
2718 }
2719
2720 if(select_mode==3)
2721 {
2722 for(int32_t y=0; y<16; ++y)
2723 {
2724 for(int32_t x=0; x<x1; ++x)
2725 {
2726 selection_grid[x+1][y+1]=0;
2727 }
2728
2729 for(int32_t x=x2+1; x<16; ++x)
2730 {
2731 selection_grid[x+1][y+1]=0;
2732 }
2733 }
2734
2735 for(int32_t x=x1; x<=x2; ++x)
2736 {
2737 for(int32_t y=0; y<y1; ++y)
2738 {
2739 selection_grid[x+1][y+1]=0;
2740 }
2741
2742 for(int32_t y=y2+1; y<16; ++y)
2743 {
2744 selection_grid[x+1][y+1]=0;
2745 }
2746 }
2747 }
2748 }
2749
2750 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2751 did_wand_select=false;
2752 }
2753
2754 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2755 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2756 bool ctrl=CHECK_CTRL_CMD;
2757 static int32_t last_tool_val = 0;
2758
2759 if(tool==t_select||tool==t_wand)
2760 {
2761 if(!drawing)
2762 {
2763 int32_t type=0;
2764
2765 if(has_selection())
2766 {
2767 if(shift)
2768 {
2769 type+=1;
2770 }
2771
2772 if(alt)
2773 {
2774 type+=2;
2775 }
2776 }
2777
2778 if(type!=select_mode)
2779 {
2780 select_mode=type;
2781
2782 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2783 set_tool_sprite(tool,type);
2784 }
2785 }
2786 }
2787 else if(alt||ctrl)
2788 {
2789 if(old_tool==-1)
2790 {
2791 old_tool = tool;
2792 tool_cur = -1;
2793 }
2794 if(alt&&ctrl)
2795 tool = t_recolor;
2796 else if(alt)
2797 tool = t_eyedropper;
2798 else tool = t_fill;
2799 }
2800 else if(old_tool!=-1)
2801 {
2802 tool = old_tool;
2803 old_tool = -1;
2804 tool_cur = -1;
2805 redraw = true;
2806 }
2807 if(last_tool_val != tool)
2808 {
2809 redraw = true;
2810 tool_cur = -1;
2811 update_tool_cursor();
2812 last_tool_val = tool;
2813 }
2814
2815 if(!bdown)
2816 {
2817 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2818 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2819 }
2820
2821 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2822 {
2823 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2824 {
2825 if(tool==t_move || tool==t_fill)
2826 {
2827 set_tool_sprite(tool,1);
2828
2829 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2830 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2831 }
2832
2833 for(int32_t i=0; i<undocount; i++)
2834 {
2835 undotile[i]=newtilebuf[tile].data[i];
2836 }
2837 for(auto x = 0; x < 16; ++x)
2838 for(auto y = 0; y < 16; ++y)
2839 undoselgrid[x][y] = selection_grid[x+1][y+1];
2840 for(auto q = 0; q < 256; ++q)
2841 undofloatsel[q] = floatsel[q];
2842 undo_is_floatsel = floating_sel;
2843
2844 drawing=1;
2845 }
2846
2847 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2848 {
2849 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2850 {
2851 done=2;
2852 }
2853 }
2854
2855 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2856 {
2857 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2858 {
2859 done=1;
2860 }
2861 }
2862
2863 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2866 {
2867 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2868 get_palette(tpal);
2869
2870 if(newtilebuf[tile].format==tf4Bit)
2871 {
2872 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2873 }
2874 else
2875 {
2876 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2877 }
2878
2879 redraw=true;
2880 }
2881 }
2882
2883 int sqr_clicked;
2884 if(show_quartgrid && qgrid_tool(tool))
2885 {
2886 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2887 if(sqr_clicked > -1)
2888 {
2889 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2890 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2891 refl_flags ^= (1<<sqr_clicked);
2892 }
2893 }
2894 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2895 if(sqr_clicked > -1)
2896 {
2897 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2898 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2899 xmode = sqr_clicked;
2900 }
2901 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2902 if(sqr_clicked > -1)
2903 {
2904 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2905 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2906 bgmode = sqr_clicked;
2907 }
2908
2909 if(showcolortip)
2910 {
2911 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2912 {
2913 showcolortip = 0;
2914 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2915 }
2916 }
2917 else
2918 {
2919 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2920 {
2921 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2922 {
2923 showcolortip = 1;
2924 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2925 redraw=true;
2926 }
2927 }
2928 }
2929
2930 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2933 {
2934 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2935 redraw=true;
2936 }
2937 }
2938 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2939 {
2940 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2941 redraw=true;
2942 }
2943 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2944 {
2945 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2946 redraw=true;
2947 }
2948
2949 switch(newtilebuf[tile].format)
2950 {
2951 case tf4Bit:
2952 {
2953 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2954 if(ind > -1)
2955 {
2956 c1 = ind;
2957 redraw=true;
2958 }
2959 break;
2960 }
2961 case tf8Bit:
2962 {
2963 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2964 if(ind > -1)
2965 {
2966 c1 = ind;
2967 redraw=true;
2968 }
2969 break;
2970 }
2971 }
2972
2973
2974 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2975 if(newtool > -1 && newtool < t_max)
2976 {
2977 tool=newtool;
2978 redraw=true;
2979 }
2980
2981 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2982 {
2983 if(do_x_button(screen, x_btn.x, x_btn.y))
2984 {
2985 done=1;
2986 }
2987 }
2988 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2989 {
2990 if(do_question_button(screen, info_btn.x, info_btn.y))
2991 {
2992 show_edit_tile_help();
2993 }
2994 }
2995
2996 bdown=true;
2997 }
2998
2999 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3000 {
3001 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3002 {
3003 if(tool==t_move || tool==t_fill)
3004 {
3005 set_tool_sprite(tool,1);
3006
3007 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3008 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3009 }
3010
3011 for(int32_t i=0; i<undocount; i++)
3012 {
3013 undotile[i]=newtilebuf[tile].data[i];
3014 }
3015 for(auto x = 0; x < 16; ++x)
3016 for(auto y = 0; y < 16; ++y)
3017 undoselgrid[x][y] = selection_grid[x+1][y+1];
3018 for(auto q = 0; q < 256; ++q)
3019 undofloatsel[q] = floatsel[q];
3020 undo_is_floatsel = floating_sel;
3021
3022 drawing=2;
3023 }
3024
3025 switch(newtilebuf[tile].format)
3026 {
3027 case tf4Bit:
3028 {
3029 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3030 if(ind > -1)
3031 {
3032 c2 = ind;
3033 redraw=true;
3034 }
3035 break;
3036 }
3037 case tf8Bit:
3038 {
3039 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3040 if(ind > -1)
3041 {
3042 c2 = ind;
3043 redraw=true;
3044 }
3045 break;
3046 }
3047 }
3048
3049 bdown=true;
3050 }
3051
3052 if(bdown&&!gui_mouse_b()) //released the buttons
3053 {
3054 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3055 {
3056 if(tool==t_move || tool==t_fill)
3057 {
3058 set_tool_sprite(tool,0);
3059 }
3060 }
3061 }
3062
3063 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3064 {
3065 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3066 int32_t x=ind%zoomtile.w;
3067 int32_t y=ind/zoomtile.w;
3068
3069 bool reset_draw = false;
3070
3071 if(__pixel_draw(x,y,tile,flip))
3072 reset_draw = true;
3073 if(show_quartgrid)
3074 {
3075 auto tmp_sel_mode = select_mode;
3076 if(tool == t_wand && select_mode == 0)
3077 select_mode = 1;
3078 if(qgrid_tool(tool))
3079 {
3080 if(refl_flags & (1<<REFL_HFLIP))
3081 if(__pixel_draw(15-x,y,tile,flip))
3082 reset_draw = true;
3083 if(refl_flags & (1<<REFL_VFLIP))
3084 if(__pixel_draw(x,15-y,tile,flip))
3085 reset_draw = true;
3086 //Diagonal flip and 180° rotation are the same!
3087 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3088 if(__pixel_draw(15-x,15-y,tile,flip))
3089 reset_draw = true;
3090 if(refl_flags & (1<<REFL_90CW))
3091 if(__pixel_draw(15-y,x,tile,flip))
3092 reset_draw = true;
3093 if(refl_flags & (1<<REFL_90CCW))
3094 if(__pixel_draw(y,15-x,tile,flip))
3095 reset_draw = true;
3096 }
3097 select_mode = tmp_sel_mode;
3098 }
3099
3100 if(reset_draw)
3101 drawing = 0;
3102 redraw=true;
3103 }
3104
3105 if(gui_mouse_b()==0)
3106 {
3107 bdown=false;
3108 drawing=0;
3109 }
3110
3111 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3112 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3113
3114 {
3115 tile_x=temp_x;
3116 tile_y=temp_y;
3117 redraw=true;
3118 }
3119
3120 const char *toolnames[t_max]=
3121 {
3122 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3123 };
3124
3125 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3126 if(toolbtn > -1 && toolbtn < t_max)
3127 {
3128 int32_t column = toolbtn%tool_btns.w;
3129 int32_t row = toolbtn/tool_btns.w;
3130
3131 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3132 redraw=true;
3133 }
3134 /* Highlight the hovered pixel? Eh, maybe too much?
3135 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3136 if(hov_pix > -1)
3137 {
3138 int32_t column = hov_pix%zoomtile.w;
3139 int32_t row = hov_pix/zoomtile.w;
3140
3141 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3142 redraw=true;
3143 }*/
3144
3145 if(redraw)
3146 {
3147 custom_vsync();
3148 draw_edit_scr(tile,flip,cs,oldtile, false);
3149 }
3150 else
3151 {
3152 bool hs=has_selection();
3153
3154 if(hs)
3155 {
3156 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3157 }
3158
3159 custom_vsync();
3160
3161 if(hs)
3162 {
3163 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3164 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3165 }
3166
3167 update_tool_cursor();
3168 SCRFIX();
3169 }
3170
3171 }
3172 while(!done);
3173
3174 unfloat_selection();
3175 clear_selection_grid();
3176
3177 while(gui_mouse_b())
3178 {
3179 /* do nothing */
3180 rest(1);
3181 }
3182
3183 if(done==1)
3184 {
3185 for(int32_t i=0; i<undocount; i++)
3186 {
3187 newtilebuf[tile].data[i]=oldtile[i];
3188 }
3189 }
3190 else
3191 {
3192 byte *buf = new byte[undocount];
3193
3194 // put back old tile
3195 for(int32_t i=0; i<undocount; i++)
3196 {
3197 buf[i] = newtilebuf[tile].data[i];
3198 newtilebuf[tile].data[i] = oldtile[i];
3199 }
3200
3201 // go
3202 go_tiles();
3203
3204 // replace old tile with new one again
3205 for(int32_t i=0; i<undocount; i++)
3206 {
3207 newtilebuf[tile].data[i] = buf[i];
3208 }
3209
3210 // usetiles=true;
3211 saved=false;
3212
3213 if(buf!=NULL)
3214 {
3215 delete[] buf;
3216 }
3217 }
3218
3219 MouseSprite::set(ZQM_NORMAL);
3220 register_blank_tiles();
3221 register_used_tiles();
3222 clear_tooltip();
3223 comeback();
3224 destroy_bitmap(selection_pattern);
3225 destroy_bitmap(selecting_pattern);
3226 destroy_bitmap(intersection_pattern);
3227 font = oldfont;
3228 popup_zqdialog_end();
3229 }
3230
3231 /* Grab Tile Code */
3232
3233 enum recolorState { rcNone, rc4Bit, rc8Bit };
3234
3235 BITMAP* original_imagebuf_bitmap=NULL;
3236 void *imagebuf=NULL;
3237 int32_t imagebuf_bitmap_scale=0;
3238 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3239 int32_t imagesize=0;
3240 int32_t tilecount=0;
3241 int32_t imagetype=0;
3242 int32_t imagex,imagey,selx,sely;
3243 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3244 bool nesmode=false;
3245 int32_t grabmask=0;
3246 recolorState recolor=rcNone;
3247 PALETTE imagepal;
3248
3249 /* bestfit_color:
3250 * Searches a palette for the color closest to the requested R, G, B value.
3251 */
3252 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3253 {
3254 int32_t bestMatch = 0; // Color with the lowest total difference so far
3255 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3256 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3257
3258 for(int32_t i = 0; i < CSET_SIZE; i++)
3259 {
3260 byte *rgbByte;
3261
3262 // This seems to be right...
3263 if(cs==2 || cs==3 || cs==4)
3264 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3265 else if(cs==9)
3266 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3267 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3268 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3269 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3270 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3271 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3272 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3273 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3274 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3275 else
3276 rgbByte = colordata + (CSET(cs)+i)*3;
3277
3278 int32_t dr=r-*rgbByte;
3279 int32_t dg=g-*(rgbByte+1);
3280 int32_t db=b-*(rgbByte+2);
3281
3282 // Track both the total color difference and the single greatest
3283 // difference of R, G, B. The idea is that it's better to have
3284 // two or three small differences than one big one.
3285 // The differences are multiplied by different numbers to account
3286 // for the differences in perceived brightness of the three colors.
3287 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3288 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3289
3290 // Perfect match? Just stop here.
3291 if(totalDiff==0)
3292 return i;
3293
3294 if(totalDiff < bestTotalDiff || // Best match so far?
3295 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3296 {
3297 bestMatch=i;
3298 bestTotalDiff=totalDiff;
3299 bestHighDiff=highDiff;
3300 }
3301 }
3302
3303 return bestMatch;
3304 }
3305
3306 // Same as the above, but draws from all colors in CSets 0-11.
3307 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3308 {
3309 int32_t bestMatch = 0;
3310 float bestTotalDiff = 100000;
3311 float bestHighDiff = 100000;
3312
3313 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3314 {
3315 byte *rgbByte;
3316
3317 int32_t cs=i>>4;
3318 if(cs==2 || cs==3 || cs==4)
3319 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3320 else if(cs==9)
3321 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3322 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3323 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3324 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3325 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3326 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3327 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3328 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3329 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3330 else
3331 rgbByte = colordata + i * 3;
3332
3333 int32_t dr=r-*rgbByte;
3334 int32_t dg=g-*(rgbByte+1);
3335 int32_t db=b-*(rgbByte+2);
3336
3337 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3338 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3339
3340 if(totalDiff==0) // Perfect match?
3341 return i;
3342
3343 if(totalDiff < bestTotalDiff || // Best match so far?
3344 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3345 {
3346 bestMatch=i;
3347 bestTotalDiff=totalDiff;
3348 bestHighDiff=highDiff;
3349 }
3350 }
3351
3352 return bestMatch;
3353 }
3354
3355 byte cset_reduce_table[PAL_SIZE];
3356
3357 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3358 {
3359 for(int32_t i=0; i<PAL_SIZE; i++)
3360 {
3361 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3362 }
3363 }
3364
3365 void calc_cset_reduce_table_8bit(PALETTE pal)
3366 {
3367 for(int32_t i=0; i<PAL_SIZE; i++)
3368 {
3369 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3370 }
3371 }
3372
3373 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3374 {
3375 //storage space for the grabbed image
3376 byte buf[64];
3377 memset(buf,0,64);
3378 byte *oldsrc=src;
3379
3380 //for 8 lines in the source image...
3381 for(int32_t line=0; line<(nesmode?4:8); line++)
3382 {
3383 //bx is the pixel at the start of a line in the storage buffer
3384 int32_t bx=line<<(nesmode?4:3);
3385 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3386 byte b=src[(bp&1)?line:line<<1];
3387
3388 //fill the storage buffer with data from the source image
3389 for(int32_t i=7; i>=0; --i)
3390 {
3391 buf[bx+i] = (b&1)+(cs<<4);
3392 b>>=1;
3393 }
3394 }
3395
3396 ++src;
3397
3398 for(int32_t p=1; p<bp; p++)
3399 {
3400 for(int32_t line=0; line<(nesmode?4:8); line++)
3401 {
3402 int32_t bx=line<<(nesmode?4:3);
3403 byte b=src[(bp&1)?line:line<<1];
3404
3405 for(int32_t i=7; i>=0; --i)
3406 {
3407 if(nesmode)
3408 {
3409 buf[bx+8+i] = (b&1)+(cs<<4);
3410 }
3411 else
3412 {
3413 buf[bx+i] |= (b&1)<<p;
3414 }
3415
3416 b>>=1;
3417 }
3418 }
3419
3420 if(p&1)
3421 {
3422 src+=15;
3423 }
3424 else
3425 {
3426 ++src;
3427 }
3428 }
3429
3430
3431 if(nesmode)
3432 {
3433 src=oldsrc;
3434
3435 for(int32_t counter=0; counter<2; ++counter, ++src)
3436 {
3437 //for 8 lines in the source image...
3438 for(int32_t line=0; line<4; line++)
3439 {
3440 //bx is the pixel at the start of a line in the storage buffer
3441 int32_t bx=line<<4;
3442 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3443 byte b=src[(line+4)<<1];
3444
3445 //fill the storage buffer with data from the source image
3446 for(int32_t i=7; i>=0; --i)
3447 {
3448 // buf[bx+i] = (b&1)+(cs<<4);
3449 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3450 b>>=1;
3451 }
3452 }
3453 }
3454 }
3455
3456 int32_t c=0;
3457
3458 switch(romtilemode)
3459 {
3460 case 0:
3461 case 1:
3462 case 2:
3463 for(int32_t j=0; j<8; j++)
3464 {
3465 for(int32_t i=0; i<8; i++)
3466 {
3467 putpixel(dest,x+i,y+j,buf[c++]);
3468 }
3469 }
3470
3471 break;
3472
3473 case 3:
3474 for(int32_t j=0; j<4; j++)
3475 {
3476 for(int32_t i=0; i<16; i++)
3477 {
3478 putpixel(dest,x+i,y+j,buf[c++]);
3479 }
3480 }
3481
3482 break;
3483 }
3484 }
3485
3486 const char *file_type[ftMAX]=
3487 {
3488 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3489 };
3490
3491 void draw_grab_window()
3492 {
3493 int w = 640;
3494 int h = 480;
3495 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3496 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3497 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3498 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3499
3500 FONT *oldfont = font;
3501 font = get_zc_font(font_lfont);
3502 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3503 font=oldfont;
3504 }
3505
3506 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3507 {
3508 width=width;
3509 height=height;
3510 white=white; // happy birthday compiler
3511
3512 int32_t yofs=0;
3513 //clear_to_color(screen2,bg);
3514 rectfill(screen2, 0, 0, 319, 159, black);
3515 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3516 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3517 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3518 yofs=3;
3519
3520 // text_mode(-1);
3521 int32_t tileromcolumns=20;
3522
3523 switch(imagetype)
3524 {
3525 case ftBMP:
3526 if(recolor==rcNone)
3527 {
3528 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3529 }
3530 else
3531 {
3532 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3533 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3534
3535 for(int32_t y=0; y<maxy; y++)
3536 {
3537 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3538 {
3539 break;
3540 }
3541
3542 for(int32_t x=0; x<maxx; x++)
3543 {
3544 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3545 {
3546 break;
3547 }
3548
3549 if(recolor==rc8Bit)
3550 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3551 else
3552 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3553 }
3554 }
3555 }
3556
3557 break;
3558
3559 case ftZGP:
3560 case ftQST:
3561 case ftZQT:
3562 case ftQSU:
3563 case ftTIL:
3564 {
3565 tiledata *hold = newtilebuf;
3566 newtilebuf = grabtilebuf;
3567 //fixme
3568 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3569 int32_t t=imagey*TILES_PER_ROW;
3570
3571 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3572 {
3573 if(t <= tilecount)
3574 {
3575 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3576 }
3577
3578 ++t;
3579 }
3580
3581 newtilebuf = hold;
3582 //fixme
3583 }
3584 break;
3585
3586 case ftBIN:
3587 {
3588 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3589 byte *buf = (byte*)imagebuf;
3590
3591 switch(romtilemode)
3592 {
3593 case 0:
3594 for(int32_t y=0; y<160; y+=8)
3595 {
3596 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3597 {
3598 puttileROM(screen2,x,y,buf+ofs,cs);
3599 ofs+=8*bp;
3600 }
3601 }
3602
3603 for(int32_t y=0; y<160; y+=8)
3604 {
3605 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3606 {
3607 puttileROM(screen2,x+128,y,buf+ofs,cs);
3608 ofs+=8*bp;
3609 }
3610 }
3611
3612 break;
3613
3614 case 1:
3615 for(int32_t y=0; y<160; y+=16)
3616 {
3617 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3618 {
3619 puttileROM(screen2,x,y,buf+ofs,cs);
3620 ofs+=8*bp;
3621 puttileROM(screen2,x,y+8,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=16)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3633 ofs+=8*bp;
3634 }
3635 }
3636
3637 break;
3638
3639 case 2:
3640 for(int32_t y=0; y<160; y+=16)
3641 {
3642 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3643 {
3644 puttileROM(screen2,x,y,buf+ofs,cs);
3645 ofs+=8*bp;
3646 puttileROM(screen2,x+8,y,buf+ofs,cs);
3647 ofs+=8*bp;
3648 puttileROM(screen2,x,y+8,buf+ofs,cs);
3649 ofs+=8*bp;
3650 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3651 ofs+=8*bp;
3652 }
3653 }
3654
3655 for(int32_t y=0; y<160; y+=16)
3656 {
3657 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3658 {
3659 puttileROM(screen2,x+128,y,buf+ofs,cs);
3660 ofs+=8*bp;
3661 puttileROM(screen2,x+136,y,buf+ofs,cs);
3662 ofs+=8*bp;
3663 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3664 ofs+=8*bp;
3665 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3666 ofs+=8*bp;
3667 }
3668 }
3669
3670 break;
3671
3672 case 3:
3673 for(int32_t y=0; y<160; y+=16)
3674 {
3675 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3676 {
3677 puttileROM(screen2,x,y,buf+ofs,cs);
3678 ofs+=8*bp;
3679 puttileROM(screen2,x,y+4,buf+ofs,cs);
3680 ofs+=8*bp;
3681 puttileROM(screen2,x,y+8,buf+ofs,cs);
3682 ofs+=8*bp;
3683 puttileROM(screen2,x,y+12,buf+ofs,cs);
3684 ofs+=8*bp;
3685 }
3686 }
3687
3688 for(int32_t y=0; y<160; y+=16)
3689 {
3690 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3691 {
3692 puttileROM(screen2,x+128,y,buf+ofs,cs);
3693 ofs+=8*bp;
3694 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3695 ofs+=8*bp;
3696 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3697 ofs+=8*bp;
3698 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3699 ofs+=8*bp;
3700 }
3701 }
3702
3703 break;
3704 }
3705 }
3706 break;
3707 }
3708
3709 tiledata hold;
3710 bool holdblank = blank_tile_table[0];
3711
3712 if(is_valid_format(newtilebuf[0].format))
3713 {
3714 hold.format = newtilebuf[0].format;
3715 hold.data = (byte *)malloc(tilesize(hold.format));
3716 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3717 }
3718 else
3719 {
3720 hold.format=tfInvalid;
3721 hold.data=NULL;
3722 }
3723
3724 newtilebuf[0].format=newformat[0];
3725 blank_tile_table[0] = false;
3726
3727 if(newtilebuf[0].data!=NULL)
3728 {
3729 free(newtilebuf[0].data);
3730 }
3731
3732 if(is_valid_format(newtilebuf[0].format))
3733 {
3734 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3735
3736 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3737 {
3738 newtilebuf[0].data[i]=newtile[i];
3739 }
3740 }
3741 else
3742 {
3743 newtilebuf[0].data=NULL;
3744 }
3745
3746 puttile16(screen2,0,208,168+yofs,cs,0);
3747 overtile16(screen2,0,232,168+yofs,cs,0);
3748 newtilebuf[0].format=hold.format;
3749 blank_tile_table[0] = holdblank;
3750
3751 if(newtilebuf[0].data!=NULL)
3752 {
3753 free(newtilebuf[0].data);
3754 }
3755
3756 if(is_valid_format(newtilebuf[0].format))
3757 {
3758 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3759
3760 for(int32_t i=0; i<256; i++)
3761 {
3762 newtilebuf[0].data[i]=hold.data[i];
3763 }
3764 }
3765 else
3766 {
3767 newtilebuf[0].data=NULL;
3768 }
3769
3770 if(hold.data!=NULL)
3771 {
3772 free(hold.data);
3773 }
3774
3775 puttile16(screen2,tile,208,192+yofs,cs,0);
3776 overtile16(screen2,tile,232,192+yofs,cs,0);
3777
3778 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3779 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3780 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3781 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3782
3783 // rect(screen2,183,167,200,184,dvc(7*2));
3784 // rect(screen2,207,167,224,184,dvc(7*2));
3785 // rect(screen2,231,167,248,184,dvc(7*2));
3786 // rect(screen2,207,191,224,208,dvc(7*2));
3787 // rect(screen2,231,191,248,208,dvc(7*2));
3788
3789 /*
3790 rect(screen2,183,167,200,184,vc(14));
3791 rect(screen2,207,167,224,184,vc(14));
3792 rect(screen2,231,167,248,184,vc(14));
3793 rect(screen2,207,191,224,208,vc(14));
3794 rect(screen2,231,191,248,208,vc(14));
3795 */
3796 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3797 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3798 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3801 int32_t screen_xofs=6;
3802 int32_t screen_yofs=25;
3803 int winh = 511;
3804 int32_t mul = 2;
3805
3806 yofs=16;
3807
3808 custom_vsync();
3809
3810 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3811
3812 // Suspend the current font while draw_text_button does its work
3813 FONT* oldfont = font;
3814
3815 font = get_zc_font(font_lfont_l);
3816
3817 int txt_x = 8*mul;
3818 int rbtn_x = 255*mul;
3819 int max_fpath_wid = rbtn_x-2-txt_x;
3820 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3821 // Interface
3822 switch(imagetype)
3823 {
3824 case 0:
3825 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3826 break;
3827
3828 case ftBMP:
3829 {
3830 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3831 int text_x = txt_x;
3832 int text_y = (216 + yofs) * mul;
3833 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3834 // int text_w = text_length(font, text.c_str());
3835 // int text_h = text_height(font);
3836 // static int grab_scale_tooltip_id = ttip_register_id();
3837 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3838 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3839
3840 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3841 break;
3842 }
3843
3844 case ftZGP:
3845 case ftQST:
3846 case ftZQT:
3847 case ftQSU:
3848 case ftTIL:
3849 case ftBIN:
3850 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3851 break;
3852 }
3853
3854 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3855 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3856
3857 if(bp==8)
3858 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3859 else
3860 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3861 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3862
3863 if(imagetype==ftBIN)
3864 {
3865 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3866 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3867 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3868 }
3869
3870 int fpath_y = (224+yofs)*mul;
3871 if(text_length(font,imagepath) <= max_fpath_wid)
3872 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3873 else
3874 {
3875 char buf[2052] = {0};
3876 strncpy(buf,imagepath,2048);
3877 int len = strlen(buf);
3878 char *ptr = buf;
3879 char *endptr = buf+len;
3880 char *it = endptr;
3881 int tmpy = fpath_y;
3882 int tmph = text_height(font)+1;
3883 while(true)
3884 {
3885 if(tmpy+tmph > (winh-2))
3886 break; //Out of space!
3887 char c = *it;
3888 bool end = !c;
3889 *it = 0;
3890 int newlen = text_length(font,ptr);
3891 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3892 {
3893 if(end) //No stored character, string ended
3894 {
3895 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 break;
3897 }
3898 char t[5];
3899 t[0] = c;
3900 for(int q = 1; q < 5; ++q)
3901 t[q] = it[q];
3902 strcpy(it,"...");
3903 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3904 for(int q = 0; q < 5; ++q)
3905 it[q] = t[q];
3906 tmpy += tmph;
3907 ptr = it;
3908 it = endptr;
3909 }
3910 else
3911 {
3912 *it = c;
3913 --it;
3914 }
3915 }
3916 }
3917 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3918 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3919 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3920 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3921
3922 //int32_t rectw = 16*mul;
3923 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3924 SCRFIX();
3925 font = oldfont;
3926 }
3927
3928 RGB_MAP rgb_table;
3929 COLOR_MAP imagepal_table;
3930
3931
3932 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3933 {
3934 //these are here to bypass compiler warnings about unused arguments
3935 x=x;
3936
3937 rgb->r = pal[y].r;
3938 rgb->g = pal[y].g;
3939 rgb->b = pal[y].b;
3940 }
3941
3942
3943 void load_imagebuf()
3944 {
3945 PACKFILE *f;
3946 //cache QRS
3947 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3948 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3949 // {
3950 // cached_rules[q] = quest_rules[q];
3951 // }
3952 bool compressed=false;
3953 bool encrypted=false;
3954 tiledata *hold=newtilebuf;
3955 zquestheader tempheader;
3956 memset(&tempheader, 0, sizeof(zquestheader));
3957
3958 if(imagebuf)
3959 {
3960 switch(imagetype)
3961 {
3962 case ftBMP:
3963 if (original_imagebuf_bitmap != imagebuf)
3964 destroy_bitmap((BITMAP*)imagebuf);
3965 destroy_bitmap(original_imagebuf_bitmap);
3966 break;
3967
3968 case ftZGP:
3969 case ftQST:
3970 case ftZQT:
3971 case ftQSU:
3972 case ftTIL:
3973 clear_tiles(grabtilebuf);
3974 break;
3975
3976 case ftBIN:
3977 free(imagebuf);
3978 break;
3979 }
3980
3981 imagebuf=NULL;
3982 original_imagebuf_bitmap=NULL;
3983 }
3984
3985 selx=sely=romofs=0;
3986 bp=4;
3987 imagetype=filetype(imagepath);
3988
3989 dword section_id;
3990 dword section_version;
3991 dword section_cversion;
3992
3993 switch(imagetype)
3994 {
3995 case ftBMP:
3996 packfile_password("");
3997 memset(imagepal, 0, sizeof(PALETTE));
3998 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
3999 imagesize = file_size_ex_password(imagepath,"");
4000 tilecount=0;
4001 create_rgb_table(&rgb_table, imagepal, NULL);
4002 rgb_map = &rgb_table;
4003 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4004
4005 if(!original_imagebuf_bitmap)
4006 {
4007 imagetype=0;
4008 }
4009 else
4010 {
4011 imagebuf = original_imagebuf_bitmap;
4012 imagebuf_bitmap_scale = 1;
4013 }
4014
4015 break;
4016
4017 case ftBIN:
4018 packfile_password("");
4019 imagesize = file_size_ex_password(imagepath, "");
4020 tilecount=0;
4021
4022 if(imagesize)
4023 {
4024 imagebuf = malloc(imagesize);
4025
4026 if(!readfile(imagepath,imagebuf,imagesize))
4027 {
4028 free(imagebuf);
4029 imagesize=0;
4030 imagetype=0;
4031 }
4032 }
4033
4034 break;
4035
4036 case ftTIL:
4037 packfile_password("");
4038 imagesize = file_size_ex_password(imagepath,"");
4039 f = pack_fopen_password(imagepath,F_READ,"");
4040
4041 if(!f)
4042 {
4043 goto error;
4044 }
4045
4046 if(!p_mgetl(&section_id,f))
4047 {
4048 goto error;
4049 }
4050
4051 if(section_id==ID_TILES)
4052 {
4053 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4054 {
4055 goto error;
4056 }
4057 }
4058
4059 error:
4060 pack_fclose(f);
4061 tilecount=count_tiles(grabtilebuf);
4062 break;
4063
4064 case ftZGP:
4065 packfile_password("");
4066 imagesize = file_size_ex_password(imagepath, "");
4067 f=pack_fopen_password(imagepath,F_READ,"");
4068
4069 if(!f)
4070 {
4071 goto error2;
4072 }
4073
4074 if(!p_mgetl(&section_id,f))
4075 {
4076 goto error2;
4077 }
4078
4079 if(section_id!=ID_GRAPHICSPACK)
4080 {
4081 goto error2;
4082 }
4083
4084 //section version info
4085 if(!p_igetw(&section_version,f))
4086 {
4087 goto error2;
4088 }
4089
4090 if(!p_igetw(&section_cversion,f))
4091 {
4092 goto error2;
4093 }
4094
4095 //tiles
4096 if(!p_mgetl(&section_id,f))
4097 {
4098 goto error2;
4099 }
4100
4101 if(section_id==ID_TILES)
4102 {
4103 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4104 {
4105 goto error2;
4106 }
4107 }
4108
4109 error2:
4110 pack_fclose(f);
4111 tilecount=count_tiles(grabtilebuf);
4112 break;
4113
4114 case ftQST:
4115 encrypted=true;
4116 case ftZQT:
4117 compressed=true;
4118 case ftQSU:
4119 packfile_password("");
4120 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4121 newtilebuf=grabtilebuf;
4122 byte skip_flags[4];
4123
4124 for(int32_t i=0; i<skip_max; ++i)
4125 {
4126 set_bit(skip_flags,i,1);
4127 }
4128
4129 set_bit(skip_flags,skip_tiles,0);
4130 set_bit(skip_flags,skip_header,0);
4131 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4132 if (ret)
4133 {
4134 imagetype=0;
4135 imagesize=0;
4136 clear_tiles(grabtilebuf);
4137 chop_path(imagepath);
4138 }
4139
4140 if (!ret && encrypted && compressed)
4141 {
4142 if(quest_access(imagepath, &tempheader) != 1)
4143 {
4144 imagetype=0;
4145 imagesize=0;
4146 clear_tiles(grabtilebuf);
4147 chop_path(imagepath);
4148 }
4149 }
4150
4151 //setPackfilePassword(NULL);
4152 newtilebuf=hold;
4153 tilecount=count_tiles(grabtilebuf);
4154 break;
4155 }
4156
4157 rgb_map = &zq_rgb_table;
4158 //restore cashed QRs / rules
4159
4160 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4161 // {
4162 // quest_rules[q] = cached_rules[q];
4163 // }
4164 }
4165
4166 static char bitstrbuf[32];
4167 bool leeching_from_tiles=false;
4168
4169 const char *bitlist(int32_t index, int32_t *list_size)
4170 {
4171 int32_t imported=2;
4172
4173 if(index>=0)
4174 {
4175 bound(index,0,leeching_from_tiles?2:1);
4176
4177 if(index==imported)
4178 {
4179 sprintf(bitstrbuf,"Imported");
4180 }
4181 else
4182 {
4183 sprintf(bitstrbuf,"%d",4<<index);
4184 }
4185
4186 return bitstrbuf;
4187 }
4188
4189 *list_size=leeching_from_tiles?3:2;
4190 return NULL;
4191 }
4192
4193 9 static ListData bit_list(bitlist, &font);
4194
4195 static DIALOG leech_dlg[] =
4196 {
4197 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4198 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4199 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4200 // 2
4201 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4202 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4203 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4204 // 5
4205 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4206 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4207 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4208 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4209 //9
4210 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4211 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4212
4213 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4214 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4215 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4216 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4218 //16
4219 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4220 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4221 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222
4223 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4224 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4225 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226
4227 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4228 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4229 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230
4231 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4232 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4233 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234
4235 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4236 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4237 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4238 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4239 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4240 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4241 };
4242
4243 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4244 {
4245 bool shift=true; // fix this!
4246 int32_t cst=0;
4247 int32_t currtile=start;
4248 int32_t height=0, width=0;
4249 byte *testtile = new byte[tilesize(tf32Bit)];
4250 byte imported_format=0;
4251 char updatestring[6];
4252 bool canadd;
4253 bool temp_canadd;
4254 bool duplicate;
4255 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4256 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4257 {
4258 0,0,0,0
4259 };
4260 BITMAP *status;
4261 status = create_bitmap_ex(8,240,140);
4262 clear_bitmap(status);
4263 sprintf(updatestring, "%d", LeechUpdate);
4264 leech_dlg[0].dp2=get_zc_font(font_lfont);
4265 leech_dlg[6].dp=updatestring;
4266
4267 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4268
4269 for(int32_t i=0; i<2; i++)
4270 {
4271 leech_dlg[i+7].flags=0;
4272 }
4273
4274 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4275
4276 for(int32_t i=0; i<12; i++)
4277 {
4278 leech_dlg[i+16].flags=0;
4279 }
4280
4281 for(int32_t i=0; i<4; i++)
4282 {
4283 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4284 }
4285
4286 leech_dlg[31].d1=0;
4287
4288 large_dialog(leech_dlg);
4289
4290 int32_t ret = do_zqdialog(leech_dlg,3);
4291
4292 if(ret==2)
4293 {
4294 delete[] testtile;
4295 return false;
4296 }
4297
4298 int32_t cdepth=leech_dlg[31].d1+1;
4299 int32_t newformat=0;
4300 auto lu = atoi(updatestring);
4301 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4302 if(LeechUpdate!=lu)
4303 {
4304 LeechUpdate=lu;
4305 zc_set_config("zquest","leech_update",LeechUpdate);
4306 }
4307 if(LeechUpdateTiles!=lut)
4308 {
4309 LeechUpdateTiles=lut;
4310 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4311 }
4312
4313 int32_t old_dupe[4];
4314 for(int32_t j=0; j<4; j++)
4315 {
4316 old_dupe[j] = DuplicateAction[j];
4317 for(int32_t i=0; i<3; i++)
4318 {
4319 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4320 {
4321 DuplicateAction[j]=i;
4322 }
4323 }
4324 }
4325 if(old_dupe[0] != DuplicateAction[0])
4326 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4327 if(old_dupe[1] != DuplicateAction[1])
4328 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4329 if(old_dupe[2] != DuplicateAction[2])
4330 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4331 if(old_dupe[3] != DuplicateAction[3])
4332 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4333
4334 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4335 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4336 {
4337 OnlyCheckNewTilesForDuplicates=ocntfd;
4338 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4339 }
4340
4341 leeching_from_tiles=false;
4342
4343 switch(imagetype)
4344 {
4345 case ftBIN:
4346 width=imagesize/128;
4347 height=1;
4348 break;
4349
4350 case ftZGP:
4351 case ftQST:
4352 case ftZQT:
4353 case ftQSU:
4354 case ftTIL:
4355 leeching_from_tiles=true;
4356 width=count_tiles(grabtilebuf);
4357 height=1;
4358 break;
4359
4360 case ftBMP:
4361 width=((((BITMAP*)imagebuf)->w)+15)/16;
4362 height=((((BITMAP*)imagebuf)->h)+15)/16;
4363 break;
4364 }
4365
4366 if(currtile+(width*height)>NEWMAXTILES)
4367 {
4368 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4369 {
4370 delete[] testtile;
4371 return false;
4372 }
4373 }
4374
4375 go_tiles();
4376 saved=false;
4377
4378 // usetiles=true;
4379 for(int32_t ty=0; ty<height; ty++) //for every row
4380 {
4381 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4382 {
4383 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4384 {
4385 FONT *oldfont = font;
4386 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4387 static bool created_tbar=false;
4388 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4389
4390 if(created_tbar)
4391 {
4392 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4393 }
4394 else
4395 {
4396 font = get_zc_font(font_lfont);
4397 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4398 font = oldfont;
4399 created_tbar=true;
4400 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4401 }
4402
4403 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4404 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4405 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4406 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4407 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4408 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4409 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4410 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4412 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4413 blit(status,screen,0, 0, 40, 20, 240, 140);
4414 SCRFIX();
4415 }
4416
4417 canadd=true;
4418
4419 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4420 {
4421 delete[] testtile;
4422 return true;
4423 }
4424
4425 switch(imagetype)
4426 {
4427 case ftBIN:
4428 break;
4429
4430 case ftZGP:
4431 case ftQST:
4432 case ftZQT:
4433 case ftQSU:
4434 case ftTIL:
4435 memset(testtile, 0, tilesize(tf32Bit));
4436 imported_format=grabtilebuf[tx].format;
4437
4438 switch(cdepth)
4439 {
4440 case 1: //4-bit
4441 newformat=tf4Bit;
4442
4443 switch(imported_format)
4444 {
4445 case tf4Bit:
4446 case tf8Bit:
4447 for(int32_t y=0; y<16; y++) //snag a tile
4448 {
4449 for(int32_t x=0; x<16; x+=2)
4450 {
4451 testtile[(y*8)+(x/2)]=
4452 (grabtilebuf[tx].data[y*16+x]&15)+
4453 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4454 }
4455 }
4456
4457 break;
4458 }
4459
4460 break;
4461
4462 case 2: //8-bit
4463 newformat=tf8Bit;
4464
4465 switch(imported_format)
4466 {
4467 case tf4Bit:
4468 unpack_tile(grabtilebuf, tx, 0, true);
4469 cst = cs&15;
4470 cst <<= CSET_SHFT;
4471
4472 for(int32_t i=0; i<256; i++)
4473 {
4474 if(!shift||unpackbuf[i]!=0)
4475 {
4476 unpackbuf[i]+=cst;
4477 }
4478 }
4479
4480 pack_tiledata(testtile, unpackbuf, tf8Bit);
4481 break;
4482
4483 case tf8Bit:
4484 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4485 break;
4486 }
4487
4488 break;
4489
4490 case 3: //original tile's bit depth
4491 newformat=imported_format;
4492 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4493 break;
4494 }
4495
4496 break;
4497
4498 case ftBMP:
4499 newformat=cdepth;
4500
4501 for(int32_t y=0; y<16; y++) //snag a tile
4502 {
4503 for(int32_t x=0; x<16; x+=2)
4504 {
4505 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4506 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4507 }
4508 }
4509
4510 break;
4511 }
4512
4513 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4514 {
4515 temp_canadd=true;
4516
4517 //check all tiles before this one
4518 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4519 {
4520 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4521 {
4522 if(DuplicateAction[flipping]>0)
4523 {
4524 if(keypressed())
4525 {
4526 delete[] testtile;
4527 return true;
4528 }
4529
4530 duplicate=(newformat==imported_format);
4531
4532 if(duplicate)
4533 {
4534 switch(flipping)
4535 {
4536 case 0: //normal
4537 if(dest[checktile].data!=NULL)
4538 {
4539 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4540 {
4541 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4542 {
4543 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4544 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4545 {
4546 duplicate=false;
4547 }
4548 }
4549 }
4550 }
4551
4552 break;
4553
4554 case 1: //horizontal
4555 if(dest[checktile].data!=NULL)
4556 {
4557 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4558 {
4559 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4560 {
4561 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4562 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4563 {
4564 duplicate=false;
4565 }
4566 }
4567 }
4568 }
4569
4570 break;
4571
4572 case 2: //vertical
4573 if(dest[checktile].data!=NULL)
4574 {
4575 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4576 {
4577 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4578 {
4579 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4580 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4581 {
4582 duplicate=false;
4583 }
4584 }
4585 }
4586 }
4587
4588 break;
4589
4590 case 3: //both
4591 if(dest[checktile].data!=NULL)
4592 {
4593 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4594 {
4595 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4596 {
4597 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4598 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4599 {
4600 duplicate=false;
4601 }
4602 }
4603 }
4604 }
4605
4606 break;
4607 }
4608 }
4609
4610 if(duplicate==true)
4611 {
4612 ++duplicates_found[flipping];
4613 ++total_duplicates_found;
4614
4615 if(DuplicateAction[flipping]>1)
4616 {
4617 ++total_duplicates_discarded;
4618 temp_canadd=false;
4619 }
4620 }
4621 }
4622
4623 canadd=canadd&&temp_canadd;
4624 }
4625 }
4626 }
4627
4628 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4629 dest[currtile].format=newformat;
4630
4631 if(dest[currtile].data!=NULL)
4632 {
4633 free(dest[currtile].data);
4634 }
4635
4636 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4637
4638 if(dest[currtile].data==NULL)
4639 {
4640 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4641 }
4642
4643 if(canadd==true)
4644 {
4645 /*
4646 for(int32_t y=0; y<16; y++)
4647 {
4648 for(int32_t x=0; x<8; x++)
4649 {
4650 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4651 }
4652 }
4653 */
4654 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4655 ++currtile;
4656 }
4657 }
4658 }
4659
4660 destroy_bitmap(status);
4661 delete[] testtile;
4662 return true;
4663 }
4664
4665 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4666 {
4667 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4668 byte format=defFormat;
4669 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4670
4671 switch(imagetype)
4672 {
4673 case ftZGP:
4674 case ftQST:
4675 case ftZQT:
4676 case ftQSU:
4677 case ftTIL:
4678 case ftBIN:
4679 case ftBMP:
4680 for(int32_t ty=0; ty<height; ty++)
4681 {
4682 for(int32_t tx=0; tx<width; tx++)
4683 {
4684 format=defFormat;
4685 switch(imagetype)
4686 {
4687 case ftZGP:
4688 case ftQST:
4689 case ftZQT:
4690 case ftQSU:
4691 case ftTIL:
4692 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4693 break;
4694 }
4695
4696 bool ever_did_unmasked = false;
4697
4698 for(int32_t y=0; y<16; y++)
4699 {
4700 for(int32_t x=0; x<16; x+=2)
4701 {
4702 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4703 if (masked)
4704 {
4705 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4706 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4707 }
4708 else
4709 {
4710 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4711 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4712 ever_did_unmasked = true;
4713 }
4714 if (format == tf4Bit)
4715 {
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4718 }
4719 }
4720 }
4721
4722 if (ever_did_unmasked)
4723 newformat[(ty*TILES_PER_ROW)+tx] = format;
4724 }
4725 }
4726
4727 break;
4728
4729 default:
4730 for(int32_t i=0; i<200; i++)
4731 {
4732 for(int32_t j=0; j<256; j++)
4733 {
4734 dest[i][j]=0;
4735 }
4736
4737 newformat[i] = tf4Bit;
4738 }
4739
4740 break;
4741 }
4742 }
4743
4744 static void scale_imagebuf_bitmap()
4745 {
4746 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4747
4748 float scale = IMAGEBUF_SCALE;
4749 int nw = original_imagebuf_bitmap->w * scale;
4750 int nh = original_imagebuf_bitmap->h * scale;
4751 if (nw <= 0 || nh <= 0)
4752 return;
4753
4754 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4755 if (!scaled_bmp)
4756 return;
4757
4758 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4759 if (imagebuf != original_imagebuf_bitmap)
4760 destroy_bitmap((BITMAP*)imagebuf);
4761 imagebuf = scaled_bmp;
4762 }
4763
4764 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4765 void grab_tile(int32_t tile,int32_t &cs)
4766 {
4767 zq_allow_tile_draw_cache = true;
4768
4769 int window_w = 640+6+6, window_h = 480+25+6;
4770 int window_x=(zq_screen_w-window_w)/2;
4771 int window_y=(zq_screen_h-window_h)/2;
4772 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4773 int window_xofs = 0;
4774 int screen_xofs=6;
4775 int screen_yofs=25;
4776 int panel_yofs=0;
4777 int bwidth = 61*1.5;
4778 int bheight = 20*1.5;
4779 int button_x = 255*2;
4780 int grab_ok_button_y = 168*2 + 32;
4781 int leech_button_x = 117*2;
4782 int leech_button_y = 166*2 + 32;
4783 int grab_cancel_button_y = 192*2 + 32;
4784 int file_button_y = 216*2 + 32;
4785 int rec_button_x = 117*2;
4786 int rec_button_y = 192*2 + 32;
4787
4788 int screen_y1 = 24;
4789 int screen_y2 = screen_y1+320-1;
4790
4791 int crect_x = 184+190;
4792 int crect_y = 168*2 + 32;
4793 int crect_w = 8*2;
4794 int crect_h = 8*2;
4795
4796 int xrect_x = 640 + 12 - 21;
4797 int xrect_y = 5;
4798
4799 byte newtile[200][256];
4800 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4801 clear_bitmap(screen3);
4802 byte newformat[200];
4803
4804 memset(newtile, 0, 200*256);
4805 memset(newformat, 0, 200);
4806
4807 static EXT_LIST list[] =
4808 {
4809 { (char *)"All Files (*.*)", NULL },
4810 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4811 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4812 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4813 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4814 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4815 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4816 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4817 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4818 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4819 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4820 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4821 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4822 { NULL, NULL }
4823 };
4824
4825
4826 memset(cset_reduce_table, 0, 256);
4827 memset(col_diff,0,3*128);
4828 bool bdown=false;
4829 int done=0;
4830 int pal=0;
4831 int f=0;
4832 int black=vc(0),white=vc(15);
4833 int selwidth=1, selheight=1;
4834 int selx2=0, sely2=0;
4835 bool xreversed=false, yreversed=false;
4836 bool doleech=false, dofile=false, dopal=false;
4837
4838 int jwin_pal2[jcMAX];
4839 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4840
4841
4842 if(imagebuf==NULL)
4843 load_imagebuf();
4844
4845 calc_cset_reduce_table(imagepal, cs);
4846 calc_cset_reduce_table_8bit(imagepal);
4847 draw_grab_window();
4848 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4849 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4850
4851 while(gui_mouse_b())
4852 {
4853 /* do nothing */
4854 rest(1);
4855 }
4856
4857 do
4858 {
4859 HANDLE_CLOSE_ZQDLG();
4860 if(exiting_program) break;
4861 rest(4);
4862 bool redraw=false;
4863
4864 if(keypressed())
4865 {
4866 redraw=true;
4867
4868 switch(readkey()>>8)
4869 {
4870 case KEY_F:
4871 dofile=true;
4872 break;
4873
4874 case KEY_L:
4875 doleech=true;
4876 break;
4877
4878 case KEY_P:
4879 if(imagetype==ftBMP)
4880 {
4881 dopal=true;
4882 recolor=rcNone;
4883 calc_cset_reduce_table(imagepal, cs);
4884 }
4885
4886 break;
4887
4888 case KEY_ESC:
4889 done=1;
4890 break;
4891
4892 case KEY_ENTER_PAD:
4893 case KEY_ENTER:
4894 done=2;
4895 break;
4896
4897 case KEY_DOWN:
4898 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4899 else ++imagey;
4900
4901 break;
4902
4903 case KEY_UP:
4904 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4905 else --imagey;
4906
4907 break;
4908
4909 case KEY_RIGHT:
4910 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4911 else ++imagex;
4912
4913 break;
4914
4915 case KEY_LEFT:
4916 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4917 else --imagex;
4918
4919 break;
4920
4921 case KEY_PGDN:
4922 imagey+=10;
4923 break;
4924
4925 case KEY_PGUP:
4926 imagey-=10;
4927 break;
4928
4929 case KEY_HOME:
4930 imagex=imagey=0;
4931 break;
4932
4933 case KEY_EQUALS:
4934 case KEY_PLUS_PAD:
4935 cs = (cs<13) ? cs+1:0;
4936 if(recolor==rc4Bit)
4937 calc_cset_reduce_table(imagepal, cs);
4938 break;
4939
4940 case KEY_MINUS:
4941 case KEY_MINUS_PAD:
4942 cs = (cs>0) ? cs-1:13;
4943 if(recolor==rc4Bit)
4944 calc_cset_reduce_table(imagepal, cs);
4945 break;
4946
4947 case KEY_S:
4948 if(grabmode==1) grabmode=8;
4949 else if(grabmode==8) grabmode=16;
4950 else grabmode=1;
4951
4952 break;
4953
4954 case KEY_COMMA:
4955 if (imagetype == ftBMP)
4956 {
4957 imagebuf_bitmap_scale--;
4958 if (imagebuf_bitmap_scale == 0)
4959 imagebuf_bitmap_scale = -2;
4960 scale_imagebuf_bitmap();
4961 }
4962 break;
4963 case KEY_STOP:
4964 if (imagetype == ftBMP)
4965 {
4966 imagebuf_bitmap_scale++;
4967 if (imagebuf_bitmap_scale == -1)
4968 imagebuf_bitmap_scale = 1;
4969 scale_imagebuf_bitmap();
4970 }
4971 break;
4972
4973 case KEY_1:
4974 if(recolor==rc8Bit)
4975 recolor=rcNone;
4976 //imagex=(imagex*bp)>>3;
4977 bp=1;
4978 //imagex<<=3;
4979 nesmode=false;
4980 break;
4981
4982 case KEY_2:
4983 if(recolor==rc8Bit)
4984 recolor=rcNone;
4985 //imagex=(imagex*bp)>>3;
4986 bp=2;
4987 //imagex<<=2;
4988 nesmode=false;
4989 break;
4990
4991 case KEY_N:
4992 if(recolor==rc8Bit)
4993 recolor=rcNone;
4994 //imagex=(imagex*bp)>>3;
4995 bp=2;
4996 //imagex<<=2;
4997 nesmode=true;
4998 break;
4999
5000 case KEY_4:
5001 if(recolor==rc8Bit)
5002 recolor=rcNone;
5003 //imagex=(imagex*bp)>>3;
5004 bp=4;
5005 //imagex<<=1;
5006 nesmode=false;
5007 break;
5008
5009 case KEY_8:
5010 //imagex=(imagex*bp)>>3;
5011 bp=8;
5012 break;
5013
5014 case KEY_B:
5015 if(bp==2&&!nesmode)
5016 {
5017 nesmode=true;
5018 }
5019 else
5020 {
5021 nesmode=false;
5022 bp<<=1;
5023
5024 if(bp==16)
5025 {
5026 bp=1;
5027 //imagex<<=3;
5028 }
5029 else
5030 {
5031 //imagex>>=1;
5032 }
5033 }
5034
5035 break;
5036
5037 case KEY_M:
5038 romtilemode=(romtilemode+1)%4;
5039 break;
5040
5041 case KEY_Z:
5042 if(romofs>0) --romofs;
5043
5044 break;
5045
5046 case KEY_X:
5047 ++romofs;
5048 break;
5049
5050 case KEY_R:
5051 if(pal)
5052 {
5053 dopal=true;
5054 }
5055
5056 if(recolor!=rcNone)
5057 recolor=rcNone;
5058 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5059 {
5060 bp=8;
5061 recolor=rc8Bit;
5062 calc_cset_reduce_table_8bit(imagepal);
5063 }
5064 else
5065 {
5066 if(bp==8)
5067 bp=4;
5068 recolor=rc4Bit;
5069 calc_cset_reduce_table(imagepal, cs);
5070 }
5071 break;
5072
5073 default:
5074 redraw=false;
5075 }
5076
5077 clear_keybuf();
5078
5079 if(imagex<0) imagex=0;
5080
5081 if(imagey<0) imagey=0;
5082
5083 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5084 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5085 }
5086
5087 //boogie!
5088 if(gui_mouse_b()==1 && !bdown)
5089 {
5090 int x=gui_mouse_x();
5091 int y=gui_mouse_y();
5092 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5093 if(do_x_button(screen, xrect_x, xrect_y))
5094 done=1;
5095
5096 if(!bdown)
5097 {
5098 bool regrab=false;
5099 bdown=true;
5100 FONT* oldfont = font;
5101 font = get_zc_font(font_lfont_l);
5102
5103 if(y>=screen_y1 && y<=screen_y2)
5104 {
5105 do
5106 {
5107 HANDLE_CLOSE_ZQDLG();
5108 if(exiting_program) break;
5109 int x = (gui_mouse_x()-screen_xofs) / 2;
5110 int y = (gui_mouse_y()-screen_yofs) / 2;
5111
5112 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5113
5114 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5115 {
5116 selx=vbound((x/grabmode)*grabmode,0,304);
5117 sely=vbound((y/grabmode)*grabmode,0,144);
5118 selx2=selx;
5119 sely2=sely;
5120 selwidth=1;
5121 selheight=1;
5122 xreversed=false;
5123 yreversed=false;
5124 }
5125 else
5126 {
5127 if(xreversed)
5128 {
5129 zc_swap(selx, selx2);
5130 xreversed=false;
5131 }
5132
5133 if(yreversed)
5134 {
5135 zc_swap(sely, sely2);
5136 yreversed=false;
5137 }
5138
5139 selx2=vbound((x/grabmode)*grabmode,0,304);
5140 sely2=vbound((y/grabmode)*grabmode,0,144);
5141 selwidth=1+(abs(selx2-selx))/16;
5142 selheight=1+(abs(sely2-sely))/16;
5143
5144 if(selx2<selx)
5145 {
5146 zc_swap(selx, selx2);
5147 xreversed=true;
5148 }
5149
5150 if(sely2<sely)
5151 {
5152 zc_swap(sely, sely2);
5153 yreversed=true;
5154 }
5155 }
5156
5157 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5158 bool redraw = changed || !(f%8);
5159
5160 if(redraw)
5161 {
5162 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5163 if(changed)
5164 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5165 if(f&8)
5166 {
5167 static const int w = 32;
5168 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5169 }
5170 }
5171 else custom_vsync();
5172
5173 ++f;
5174 }
5175 while(gui_mouse_b());
5176 }
5177 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5178 {
5179 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5180 done=2;
5181 }
5182 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5183 {
5184 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5185 {
5186 doleech=true;
5187 }
5188 }
5189 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5190 {
5191 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5192 done=1;
5193 }
5194 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5195 {
5196 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5197 {
5198 dofile=true;
5199 }
5200 }
5201 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5202 {
5203 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5204 {
5205 if(pal)
5206 {
5207 dopal = true;
5208 }
5209
5210 if(recolor!=rcNone)
5211 recolor=rcNone;
5212 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5213 {
5214 bp=8;
5215 recolor=rc8Bit;
5216 calc_cset_reduce_table_8bit(imagepal);
5217 }
5218 else
5219 {
5220 if(bp==8)
5221 bp=4;
5222 recolor=rc4Bit;
5223 calc_cset_reduce_table(imagepal, cs);
5224 }
5225 redraw=true;
5226 }
5227 }
5228 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5229 {
5230 regrab=true;
5231 grabmask^=1;
5232 }
5233 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5234 {
5235 regrab=true;
5236 grabmask^=2;
5237 }
5238 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5239 {
5240 regrab=true;
5241 grabmask^=4;
5242 }
5243 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5244 {
5245 regrab=true;
5246 grabmask^=8;
5247 }
5248
5249 if(regrab)
5250 {
5251 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5252 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5253 redraw=true;
5254 }
5255
5256 font = oldfont;
5257 }
5258 }
5259
5260 if(gui_mouse_b()==0)
5261 bdown=false;
5262
5263 if(dofile)
5264 {
5265 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5266 {
5267 zc_set_palette(RAMpal);
5268 pal=0;
5269 white=vc(15);
5270 black=vc(0);
5271 strcpy(imagepath,temppath);
5272 load_imagebuf();
5273 imagex=imagey=0;
5274 calc_cset_reduce_table(imagepal, cs);
5275 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5276 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5277 }
5278
5279 while(key[KEY_ESC])
5280 {
5281 poll_keyboard();
5282 /* do nothing */
5283 rest(1);
5284 }
5285
5286 clear_keybuf();
5287 dofile=false;
5288 redraw=true;
5289 }
5290
5291 if(doleech)
5292 {
5293 if(leech_tiles(newtilebuf,tile,cs))
5294 {
5295 done=1;
5296 }
5297 else
5298 {
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 redraw=true;
5308 }
5309
5310 doleech=false;
5311 }
5312
5313 if(dopal)
5314 {
5315 pal^=1;
5316
5317 if(pal)
5318 {
5319 get_bw(imagepal,black,white);
5320
5321 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5322 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5323 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5324 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5325 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5326 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5327 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5328 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5329 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5330 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5331 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5332 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5333 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5334 gui_bg_color=jwin_pal[jcBOX];
5335 gui_fg_color=jwin_pal[jcBOXFG];
5336 jwin_set_colors(jwin_pal);
5337 }
5338 else
5339 {
5340 white=vc(15);
5341 black=vc(0);
5342
5343 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5344 gui_bg_color=jwin_pal[jcBOX];
5345 gui_fg_color=jwin_pal[jcBOXFG];
5346 jwin_set_colors(jwin_pal);
5347 }
5348
5349 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5350
5351 dopal=false;
5352 redraw=true;
5353 }
5354
5355 if(redraw)
5356 {
5357 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5358 }
5359 else
5360 {
5361 custom_vsync();
5362 }
5363
5364 if((f%8)==0)
5365 {
5366 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5367
5368 int selxl = selx* 2;
5369 int selyl = sely* 2;
5370 int w = 32;
5371
5372 if(f&8)
5373 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5374
5375 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5376 }
5377
5378 // SCRFIX();
5379 ++f;
5380
5381 }
5382 while(!done);
5383
5384 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5385 gui_bg_color=jwin_pal[jcBOX];
5386 gui_fg_color=jwin_pal[jcBOXFG];
5387 jwin_set_colors(jwin_pal);
5388
5389
5390 if(done==2)
5391 {
5392 go_tiles();
5393 saved=false;
5394
5395 // usetiles=true;
5396 for(int y=0; y<selheight; y++)
5397 {
5398 for(int x=0; x<selwidth; x++)
5399 {
5400 int temptile=tile+((TILES_PER_ROW*y)+x);
5401 int format=(bp==8) ? tf8Bit : tf4Bit;
5402
5403 if(newtilebuf[temptile].data!=NULL)
5404 free(newtilebuf[temptile].data);
5405
5406 newtilebuf[temptile].format=format;
5407 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5408
5409 if(newtilebuf[temptile].data==NULL)
5410 {
5411 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5412 break;
5413 }
5414
5415 for(int i=0; i<256; i++)
5416 {
5417 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5418 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5419 }
5420
5421 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5422 }
5423 }
5424 }
5425
5426 destroy_bitmap(screen3);
5427
5428 if(pal)
5429 zc_set_palette(RAMpal);
5430
5431 recolor=rcNone;
5432 calc_cset_reduce_table(imagepal, cs);
5433 register_blank_tiles();
5434 popup_zqdialog_end();
5435
5436 zq_allow_tile_draw_cache = false;
5437 }
5438
5439 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5440 bool tile_is_used(int32_t tile)
5441 {
5442 return used_tile_table[tile];
5443 }
5444 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5445 {
5446 draw_tiles(screen2, first, cs, f, true);
5447 }
5448 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5449 {
5450 clear_bitmap(dest);
5451 BITMAP *buf = create_bitmap_ex(8,16,16);
5452
5453 int32_t w = 16;
5454 int32_t h = 16;
5455
5456 if(large)
5457 {
5458 w *=2;
5459 h *=2;
5460 }
5461
5462 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5463 {
5464 int32_t x = (i%TILES_PER_ROW)<<4;
5465 int32_t y = (i/TILES_PER_ROW)<<4;
5466 int32_t l = 16;
5467
5468 if(large)
5469 {
5470 x*=2;
5471 y*=2;
5472 l*=2;
5473 }
5474
5475 l-=2;
5476
5477 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5478 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5479 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5480 {
5481 if(!true_empty) //Use pure color 0; no effects
5482 {
5483 if (InvalidBG == 2)
5484 {
5485 draw_checkerboard(dest, x, y, w);
5486 }
5487 else if(InvalidBG == 1)
5488 {
5489 for(int32_t dy=0; dy<=l+1; dy++)
5490 {
5491 for(int32_t dx=0; dx<=l+1; dx++)
5492 {
5493 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5494 }
5495 }
5496 }
5497 else
5498 {
5499 for(int32_t dy=0; dy<=l+1; dy++)
5500 {
5501 for(int32_t dx=0; dx<=l+1; dx++)
5502 {
5503 dest->line[dy+(y)][dx+(x)]=vc(0);
5504 }
5505 }
5506 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5507 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5508 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5509 }
5510 }
5511 }
5512 else
5513 {
5514 puttile16(buf,first+i,0,0,cs,0);
5515 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5516 }
5517
5518 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5519 {
5520 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5521 }
5522 }
5523
5524 destroy_bitmap(buf);
5525 }
5526
5527 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5528 {
5529 int32_t yofs=3;
5530 BITMAP *buf = create_bitmap_ex(8,16,16);
5531 int32_t mul = 2;
5532 FONT *tfont = get_zc_font(font_pfont);
5533
5534 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5535 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5536 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5537 tfont = get_zc_font(font_lfont_l);
5538
5539 // Copied tile and numbers
5540 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5541 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5542 if(copy>=0)
5543 {
5544 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5545 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5546
5547 if(copycnt>1)
5548 {
5549 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5550 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5551 }
5552 else
5553 {
5554 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5555 }
5556 }
5557 else // No tiles copied
5558 {
5559 if (InvalidBG == 2)
5560 {
5561 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5562 }
5563 else if(InvalidBG == 1)
5564 {
5565 for(int32_t dy=0; dy<16*mul; dy++)
5566 {
5567 for(int32_t dx=0; dx<16*mul; dx++)
5568 {
5569 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5570 }
5571 }
5572 }
5573 else
5574 {
5575 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5576 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5577 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5578 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5579 }
5580 }
5581
5582
5583 // Current tile
5584 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5585 puttile16(buf,tile,0,0,cs,0);
5586 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5587
5588 // Current selection mode
5589 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5590 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5591
5592 if(tile>tile2)
5593 {
5594 zc_swap(tile,tile2);
5595 }
5596
5597 char tbuf[8];
5598 tbuf[0]=0;
5599
5600 if(tile2!=tile)
5601 {
5602 sprintf(tbuf,"-%d",tile2);
5603 }
5604
5605 // Current tile and CSet text
5606 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5607 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5608 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5609
5610 FONT *tf = font;
5611 font = tfont;
5612
5613 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5614 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5615 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5617 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5618
5619 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5620 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5621 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5622 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5623
5624 font = tf;
5625
5626 int32_t w = 640;
5627 int32_t h = 480;
5628 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5629 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5630 int32_t screen_xofs=window_xofs+6;
5631 int32_t screen_yofs=window_yofs+25;
5632
5633 custom_vsync();
5634 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5635 SCRFIX();
5636 destroy_bitmap(buf);
5637 }
5638
5639 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5640 {
5641 int32_t yofs=3;
5642 BITMAP *buf = create_bitmap_ex(8,16,16);
5643 int32_t mul = 2;
5644 FONT *tfont = get_zc_font(font_pfont);
5645
5646 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5647 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5648 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5649 tfont = get_zc_font(font_lfont_l);
5650
5651 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5652
5653 if(copy>=0)
5654 {
5655 puttile16(buf,copy,0,0,cs,flip);
5656 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5657 }
5658 else
5659 {
5660 if (InvalidBG == 2)
5661 {
5662 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5663 }
5664 else if(InvalidBG == 1)
5665 {
5666 for(int32_t dy=0; dy<16*mul; dy++)
5667 {
5668 for(int32_t dx=0; dx<16*mul; dx++)
5669 {
5670 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5671 }
5672 }
5673 }
5674 else
5675 {
5676 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5677 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5678 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5679 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5680 }
5681 }
5682
5683 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5684 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5685 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5686
5687 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5688 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5689
5690 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5691 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5692
5693 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5694 {
5695 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5696 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5697 }
5698
5699 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5700 puttile16(buf,tile,0,0, cs,
5701 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5702 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5703
5704 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5705 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5706 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5707 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5708
5709 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5710 {
5711 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5712 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5713 }
5714
5715 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5716 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5717 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5718 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5719
5720
5721 int32_t w = 640;
5722 int32_t h = 480;
5723 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5724 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5725 int32_t screen_xofs=window_xofs+6;
5726 int32_t screen_yofs=window_yofs+25;
5727
5728 custom_vsync();
5729 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5730 SCRFIX();
5731 destroy_bitmap(buf);
5732 }
5733 /*
5734 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5735 {
5736 buf[t].format=format;
5737 if (buf[t].data!=NULL)
5738 {
5739 free(buf[t].data);
5740 }
5741 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5742 if (buf[t].data==NULL)
5743 {
5744 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5745 }
5746 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5747 {
5748 buf[t].data[i]=0;
5749 }
5750 }
5751 */
5752
5753 int32_t hide_used()
5754 {
5755 show_only_unused_tiles ^= 1;
5756 return D_O_K;
5757 }
5758 int32_t hide_unused()
5759 {
5760 show_only_unused_tiles ^= 2;
5761 return D_O_K;
5762 }
5763 int32_t hide_blank()
5764 {
5765 show_only_unused_tiles ^= 4;
5766 return D_O_K;
5767 }
5768 int32_t hide_8bit_marker()
5769 {
5770 show_only_unused_tiles ^= 8;
5771 return D_O_K;
5772 }
5773
5774 enum
5775 {
5776 MENUID_SELTILE_VIEW_HIDE_USED,
5777 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5778 MENUID_SELTILE_VIEW_HIDE_BLANK,
5779 MENUID_SELTILE_VIEW_HIDE_8BIT,
5780 };
5781
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5782 45 {
5783
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5784
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5785
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5786
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5787 };
5788
5789 9 static std::function<void(int)> select_tile_color_depth_cb;
5790
5791 static void set_tile_color_depth_4()
5792 {
5793 select_tile_color_depth_cb(tf4Bit);
5794 }
5795 static void set_tile_color_depth_8()
5796 {
5797 select_tile_color_depth_cb(tf8Bit);
5798 }
5799 enum
5800 {
5801 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5802 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5803 };
5804
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5805 27 {
5806
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5807
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5808 };
5809
5810 //returns the row the tile is in on its page
5811 int32_t tile_page_row(int32_t tile)
5812 {
5813 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5814 }
5815
5816 enum {ti_none, ti_encompass, ti_broken};
5817
5818 //striped check and striped selection
5819 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5820 {
5821 int32_t cmb_first = cmb.o_tile;
5822 int32_t cmb_last = cmb.o_tile;
5823 do
5824 {
5825 cmb_last = cmb.tile;
5826 animate(cmb, true);
5827 }
5828 while(cmb.tile != cmb.o_tile);
5829 reset_combo_animation(cmb);
5830 cmb_first += offset;
5831 cmb_last += offset;
5832
5833 if(cmb_first > selection_last || cmb_last < selection_first)
5834 return ti_none;
5835 if(cmb_first >= selection_first && cmb_last <= selection_last)
5836 return ti_encompass;
5837
5838 do
5839 {
5840 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5841 {
5842 reset_combo_animation(cmb);
5843 return ti_broken; //contained, but non-encompassing.
5844 }
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 return ti_none;
5850 }
5851 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5852 {
5853 // if selection is before or after check...
5854 if((check_first>selection_last)||(selection_first>check_last))
5855 {
5856 return ti_none;
5857 }
5858
5859 // if selection envelopes check
5860 if((selection_first<=check_first)&&(selection_last>=check_last))
5861 {
5862 return ti_encompass; //encompass
5863 }
5864
5865 //everything else is a break
5866 return ti_broken; //intersect
5867 }
5868
5869
5870
5871 //rectangular check and striped selection
5872 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5873 {
5874 int32_t ret1=-1, ret2=-1;
5875
5876 for(int32_t i=0; i<check_height; ++i)
5877 {
5878 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5879 int32_t check_last=check_first+check_width-1;
5880 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5881
5882 if(ret2==ti_broken)
5883 {
5884 return ti_broken;
5885 }
5886
5887 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5888 }
5889
5890 if(ret1==ti_encompass)
5891 {
5892 if((TILEROW(selection_first)<=check_top) &&
5893 (TILEROW(selection_last)>=(check_top+check_height-1)))
5894 {
5895 return ti_encompass;
5896 }
5897 else
5898 {
5899 return ti_broken;
5900 }
5901 }
5902
5903 return ti_none;
5904 }
5905
5906
5907 //striped check and rectangular selection
5908 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5909 {
5910 if(selection_width < TILES_PER_ROW)
5911 {
5912 int32_t cmb_first = cmb.o_tile;
5913 int32_t cmb_last = cmb.o_tile;
5914 do
5915 {
5916 cmb_last = cmb.tile;
5917 animate(cmb, true);
5918 }
5919 while(cmb.tile != cmb.o_tile);
5920 reset_combo_animation(cmb);
5921 cmb_first += offset;
5922 cmb_last += offset;
5923
5924 if((TILEROW(cmb_first)>=selection_top) &&
5925 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5926 (TILECOL(cmb_first)>=selection_left) &&
5927 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5928 {
5929 return ti_encompass;
5930 }
5931 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5932 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5933 {
5934 return ti_none;
5935 }
5936
5937 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5938 {
5939 int32_t firstcol = TILECOL(cmb_first);
5940 int32_t lastcol = TILECOL(cmb_last);
5941
5942 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5943 return ti_none;
5944 else //handle skip x
5945 {
5946 do
5947 {
5948 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5949 {
5950 reset_combo_animation(cmb);
5951 return ti_broken;
5952 }
5953 animate(cmb, true);
5954 }
5955 while(cmb.tile != cmb.o_tile);
5956 reset_combo_animation(cmb);
5957 return ti_none;
5958 }
5959 }
5960 else //multi-row combo...
5961 {
5962 int32_t row = TILEROW(cmb_first);
5963
5964 do
5965 {
5966 if(row < selection_top || row > selection_top+selection_height-1)
5967 {
5968 //This row isn't in the selection; skip to next row
5969 do
5970 {
5971 animate(cmb,true);
5972 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5973 }
5974 while(TILEROW(cmb.tile) == row);
5975 row = TILEROW(cmb.tile);
5976 continue;
5977 }
5978
5979 //This row IS in the selection; check each tile.
5980 do
5981 {
5982 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5983 {
5984 reset_combo_animation(cmb);
5985 return ti_broken;
5986 }
5987 animate(cmb, true);
5988 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5989 }
5990 while(TILEROW(cmb.tile) == row);
5991 row = TILEROW(cmb.tile);
5992 }
5993 while(cmb.tile != cmb.o_tile);
5994
5995 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5996 }
5997 }
5998
5999 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6000 }
6001 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6002 {
6003 if(selection_width < TILES_PER_ROW)
6004 {
6005 if((check_last-check_first+1<=selection_width) &&
6006 (TILEROW(check_first)>=selection_top) &&
6007 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6008 (TILECOL(check_first)>=selection_left) &&
6009 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6010 {
6011 return ti_encompass;
6012 }
6013 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6014 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6015 {
6016 return ti_none;
6017 }
6018
6019 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6020
6021 //one last base case: the strip we're interested in only lies along one row
6022 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6023 {
6024 int32_t cfcol = check_first%TILES_PER_ROW;
6025 int32_t clcol = check_last%TILES_PER_ROW;
6026
6027 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6028 return ti_none;
6029 else
6030 return ti_broken;
6031 }
6032 else
6033 {
6034 //recursively cut the strip into substrips which lie entirely on one row
6035 int32_t currow = check_first/TILES_PER_ROW;
6036 int32_t endrow = check_last/TILES_PER_ROW;
6037 int32_t accum = 0;
6038 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6039
6040 for(++currow; currow<endrow; currow++)
6041 {
6042 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6043 }
6044
6045 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6046
6047 if(accum > 0)
6048 return ti_broken;
6049
6050 return ti_none;
6051 }
6052 }
6053
6054 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6055 }
6056
6057 //rectangular check and rectangular selection
6058 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6059 {
6060 if((check_left>=selection_left) &&
6061 (check_left+check_width<=selection_left+selection_width) &&
6062 (check_top>=selection_top) &&
6063 (check_top+check_height<=selection_top+selection_height))
6064 {
6065 return ti_encompass;
6066 }
6067 else
6068 {
6069 for(int32_t i=check_top; i<check_top+check_height; ++i)
6070 {
6071 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6072 {
6073 return ti_broken;
6074 }
6075 }
6076 }
6077
6078 return ti_none;
6079 }
6080
6081
6082
6083
6084 static DIALOG move_textbox_list_dlg[] =
6085 {
6086 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6087 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6088 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6089 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6090 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6091 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6092 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6093 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6094 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6095 };
6096
6097 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6098 {
6099 char buf1[512] = {0};
6100 char buf2[512] = {0};
6101 large_dialog(move_textbox_list_dlg);
6102 DIALOG& tbox = move_textbox_list_dlg[3];
6103 {
6104 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6105 int indx = 0, word_indx = 0;
6106 for(char c : msg)
6107 {
6108 if(c == ' ' || c == '\n')
6109 word_indx = indx;
6110 buf1[indx++] = c;
6111 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6112 {
6113 buf1[word_indx] = 0;
6114 strcpy(buf2, msg.c_str()+word_indx+1);
6115 break;
6116 }
6117 }
6118 }
6119
6120 move_textbox_list_dlg[0].dp = (void*)title;
6121 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6122 move_textbox_list_dlg[1].dp = buf1;
6123 move_textbox_list_dlg[2].dp = buf2;
6124 tbox.dp = textbox;
6125 tbox.d2 = 0;
6126 auto tby = tbox.y;
6127 auto tbh = tbox.h;
6128 if(!buf2[0])
6129 {
6130 auto diff = move_textbox_list_dlg[2].h;
6131 tbox.y -= diff;
6132 tbox.h += diff;
6133 }
6134
6135 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6136 position_mouse_z(0);
6137 tbox.y = tby;
6138 tbox.h = tbh;
6139
6140 return ret == 4;
6141 }
6142
6143 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6144 {
6145 return a==0?b:a==1?c:d;
6146 }
6147
6148 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6149 {
6150 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6151 int i = ti_none;
6152 auto t = ref->getTile() + ref->offset();
6153
6154 if(combo_ref)
6155 {
6156 if(proc.rect)
6157 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6158 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6159 }
6160 else if(proc.rect)
6161 {
6162 if(ref->h > 1)
6163 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6164 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6165 }
6166 else
6167 {
6168 if(ref->h > 1)
6169 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6170 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6171 }
6172
6173 bool in = i != ti_none, out = i != ti_encompass;
6174 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6175 {
6176 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6177 if(proc.rect)
6178 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6179 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6180 if(i != ti_none)
6181 in = true;
6182 if(i != ti_encompass)
6183 out = true;
6184 }
6185 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6186
6187 if(i != ti_none && ref->getTile() != 0)
6188 {
6189 if(mode == Mode::CHECK_ALL)
6190 {
6191 move_refs.emplace_back(std::move(ref));
6192 return true;
6193 }
6194 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6195 {
6196 if(warning_flood || warning_list.tellp() >= 65000)
6197 {
6198 if(!warning_flood)
6199 warning_list << "...\n...\n...\nmany others";
6200 warning_flood = true;
6201 }
6202 else
6203 warning_list << ref->name << '\n';
6204 }
6205 else if(i==ti_encompass)
6206 {
6207 move_refs.emplace_back(std::move(ref));
6208 return true;
6209 }
6210 }
6211 return false;
6212 }
6213
6214 bool TileMoveList::check_prot()
6215 {
6216 if(!TileProtection)
6217 return true;
6218 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6219
6220 warning_flood = false;
6221 warning_list.clear();
6222
6223 return ret;
6224 }
6225
6226 void TileMoveList::add_diff(int diff)
6227 {
6228 for(auto& ref : move_refs)
6229 ref->addTile(diff);
6230 }
6231
6232 //from 'combo.h'
6233 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6234 {
6235 int i = ti_none;
6236 auto c = ref->getCombo();
6237
6238 if(ref->no_move)
6239 processed_combos[c] = true;
6240 else processed_combos[c]; //inserts element if does not exist
6241 i = move_intersection_ss(c, c, proc._first, proc._last);
6242
6243 if(i != ti_none && ref->getCombo() != 0)
6244 {
6245 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6246 {
6247 if(ComboProtection)
6248 {
6249 if(warning_flood || warning_list.tellp() >= 65000)
6250 {
6251 if(!warning_flood)
6252 warning_list << "...\n...\n...\nmany others";
6253 warning_flood = true;
6254 }
6255 else
6256 warning_list << ref->name << '\n';
6257 }
6258 }
6259 else if(i==ti_encompass)
6260 {
6261 move_refs.emplace_back(std::move(ref));
6262 return true;
6263 }
6264 }
6265 return false;
6266 }
6267
6268 bool ComboMoveList::check_prot()
6269 {
6270 if(!ComboProtection)
6271 return true;
6272 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6273 bool subset_header = false;
6274 for(int q = 0; q < 2; ++q)
6275 {
6276 bool is_dest = (q==1);
6277 if(!is_dest && !source_process)
6278 continue;
6279 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6280 for(auto it = subset.begin(); it != subset.end();)
6281 {
6282 auto s = *it;
6283 if(warning_flood || warning_list.tellp() >= 65000)
6284 {
6285 if(!warning_flood)
6286 warning_list << "...\n...\n...\nmany others";
6287 warning_flood = true;
6288 break;
6289 }
6290 set<int> in_set, out_set;
6291 bool no_move = is_dest;
6292 for(int c : *s)
6293 {
6294 int i = move_intersection_ss(c, c, proc._first, proc._last);
6295 if(i != ti_none)
6296 in_set.insert(c);
6297 if(i != ti_encompass)
6298 out_set.insert(c);
6299 if(!no_move)
6300 {
6301 auto it = processed_combos.find(c);
6302 if(it != processed_combos.end() && it->second)
6303 no_move = true;
6304 }
6305 }
6306 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6307 if(i == ti_encompass && !no_move)
6308 {
6309 it = subset.erase(it);
6310 continue;
6311 }
6312 if(i == ti_none)
6313 {
6314 ++it;
6315 continue;
6316 }
6317
6318 if(!subset_header)
6319 {
6320 subset_header = true;
6321 warning_list << "===== Broken Relative Combo Groups =====\n";
6322 }
6323 bool comma = false;
6324 warning_list << "In(";
6325 for(int c : in_set)
6326 {
6327 if(comma)
6328 warning_list << ",";
6329 else comma = true;
6330 warning_list << c;
6331 }
6332 warning_list << "),Out(";
6333 comma = false;
6334 for(int c : out_set)
6335 {
6336 if(comma)
6337 warning_list << ",";
6338 else comma = true;
6339 warning_list << c;
6340 }
6341 warning_list << ")\n";
6342 it = subset.erase(it);
6343 }
6344 }
6345 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6346
6347 processed_combos.clear();
6348 warning_flood = false;
6349 warning_list.clear();
6350
6351 return ret;
6352 }
6353
6354 void ComboMoveList::add_diff(int diff)
6355 {
6356 for(auto& ref : move_refs)
6357 ref->addCombo(diff);
6358 }
6359
6360 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6361 {
6362 bool BSZ2 = get_qr(qr_BSZELDA);
6363 bool move = source_process.has_value();
6364 TileMoveUndo local_undo;
6365 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6366 auto& vec = storage.vec;
6367 storage.diff = diff;
6368 storage.state = false;
6369
6370 //Combos
6371 {
6372 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6373 dest_process, source_process, mode,
6374 move
6375 ? "The tiles used by the following combos will be partially cleared by the move."
6376 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6377 ));
6378 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6379 {
6380 auto& cmb = combobuf[q];
6381 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6382 : fmt::format(" ({})", cmb.label));
6383 movelist->add_combo(&cmb, lbl);
6384
6385 //type-specific
6386 char const* type_name = ZI.getComboTypeName(cmb.type);
6387 switch(cmb.type)
6388 {
6389 case cSPOTLIGHT:
6390 {
6391 if(!(cmb.usrflags & cflag1))
6392 break;
6393 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6394 break;
6395 }
6396 }
6397 }
6398 if(!every_proc && !movelist->check_prot())
6399 return false;
6400 }
6401 //Items
6402 {
6403 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6404 dest_process, source_process, mode,
6405 move
6406 ? "The tiles used by the following items will be partially cleared by the move."
6407 : "The tiles used by the following items will be partially or completely overwritten by this process."
6408 ));
6409 build_bii_list(false);
6410 for(int32_t u=0; u<MAXITEMS; u++)
6411 {
6412 auto id = bii[u].i;
6413 itemdata& itm = itemsbuf[id];
6414 if(itm.family == itype_bottle)
6415 {
6416 vector<std::tuple<int,int,int>> rects;
6417 auto fr = itm.frames;
6418 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6419 {
6420 bottletype const& bt = QMisc.bottle_types[q];
6421 if(bt.is_blank())
6422 continue;
6423 rects.emplace_back(fr+q*fr, fr, 1);
6424 }
6425 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6426 false, 0, 0, rects);
6427 }
6428 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6429 }
6430 if(!every_proc && !movelist->check_prot())
6431 return false;
6432 }
6433 //Weapon sprites
6434 {
6435 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6436 dest_process, source_process, mode,
6437 move
6438 ? "The tiles used by the following weapons will be partially cleared by the move."
6439 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6440 ));
6441 build_biw_list();
6442
6443 for(int32_t u=0; u<MAXWPNS; u++)
6444 {
6445 bool ignore_frames=false;
6446 int32_t m=0;
6447
6448 auto id = biw[u].i;
6449 auto& wpn = wpnsbuf[id];
6450
6451 switch(biw[u].i)
6452 {
6453 case wSWORD:
6454 case wWSWORD:
6455 case wMSWORD:
6456 case wXSWORD:
6457 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6458 break;
6459
6460 case wSWORDSLASH:
6461 case wWSWORDSLASH:
6462 case wMSWORDSLASH:
6463 case wXSWORDSLASH:
6464 m=4;
6465 break;
6466
6467 case iwMMeter:
6468 m=9;
6469 break;
6470
6471 case wBRANG:
6472 case wMBRANG:
6473 case wFBRANG:
6474 m=BSZ2?1:3;
6475 break;
6476
6477 case wBOOM:
6478 case wSBOOM:
6479 case ewBOOM:
6480 case ewSBOOM:
6481 ignore_frames=true;
6482 m=2;
6483 break;
6484
6485 case wWAND:
6486 m=1;
6487 break;
6488
6489 case wMAGIC:
6490 m=1;
6491 break;
6492
6493 case wARROW:
6494 case wSARROW:
6495 case wGARROW:
6496 case ewARROW:
6497 m=1;
6498 break;
6499
6500 case wHAMMER:
6501 m=8;
6502 break;
6503
6504 case wHSHEAD:
6505 m=1;
6506 break;
6507
6508 case wHSCHAIN_H:
6509 m=1;
6510 break;
6511
6512 case wHSCHAIN_V:
6513 m=1;
6514 break;
6515
6516 case wHSHANDLE:
6517 m=1;
6518 break;
6519
6520 case iwDeath:
6521 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6522 {
6523 ignore_frames = true;
6524 m=BSZ2?4:2;
6525 }
6526 break;
6527
6528 case iwSpawn:
6529 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6530 {
6531 ignore_frames = true;
6532 m=3;
6533 }
6534 break;
6535 }
6536
6537 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6538 1, fmt::format("{} {}", biw[u].s, id));
6539
6540 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6541 //...these can't be updated by a move.
6542 if((u==3)||(u==9))
6543 {
6544 static int32_t impact_tiles[2] = {54,54};
6545 auto& tile = impact_tiles[u==3 ? 0 : 1];
6546 tile = 54; //dummy tile, ensure it's correct
6547 movelist->add_tile(&tile, 2, 1,
6548 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6549 true);
6550 }
6551 }
6552 if(!every_proc && !movelist->check_prot())
6553 return false;
6554 }
6555 //Player sprites
6556 {
6557 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6558 dest_process, source_process, mode,
6559 move
6560 ? "The tiles used by the following player sprites will be partially cleared by the move."
6561 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6562 ));
6563 {
6564 int32_t a_style=(zinit.heroAnimationStyle);
6565 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6566 do \
6567 { \
6568 movelist->add_tile(&ref_sprite[spr_tile], \
6569 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6570 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6571 name, false, \
6572 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6573 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6574 } while(false)
6575 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6576
6577 for(int32_t i=0; i<4; ++i)
6578 {
6579 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6580 }
6581
6582 for(int32_t i=0; i<4; ++i)
6583 {
6584 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6585 }
6586
6587 for(int32_t i=0; i<4; ++i)
6588 {
6589 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6590 }
6591
6592 for(int32_t i=0; i<4; ++i)
6593 {
6594 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6595 }
6596
6597 for(int32_t i=0; i<2; ++i)
6598 {
6599 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6600 }
6601
6602 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6603
6604 for(int32_t i=0; i<4; ++i)
6605 {
6606 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6607 }
6608
6609 for(int32_t i=0; i<4; ++i)
6610 {
6611 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6612 }
6613
6614 for(int32_t i=0; i<4; ++i)
6615 {
6616 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6617 }
6618
6619 for(int32_t i=0; i<2; ++i)
6620 {
6621 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6622 }
6623
6624 for(int32_t i=0; i<4; ++i)
6625 {
6626 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6627 }
6628
6629 for(int32_t i=0; i<4; ++i)
6630 {
6631 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6632 }
6633 for(int32_t i=0; i<4; ++i)
6634 {
6635 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6636 }
6637 for(int32_t i=0; i<4; ++i)
6638 {
6639 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6640 }
6641 for(int32_t i=0; i<4; ++i)
6642 {
6643 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6644 }
6645 for(int32_t i=0; i<4; ++i)
6646 {
6647 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6648 }
6649 for(int32_t i=0; i<4; ++i)
6650 {
6651 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6652 }
6653 for(int32_t i=0; i<4; ++i)
6654 {
6655 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6656 }
6657 for(int32_t i=0; i<4; ++i)
6658 {
6659 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6660 }
6661 //69
6662 for(int32_t i=0; i<4; ++i)
6663 {
6664 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6665 }
6666 //73
6667 for(int32_t i=0; i<4; ++i)
6668 {
6669 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6670 }
6671 //77
6672 for(int32_t i=0; i<4; ++i)
6673 {
6674 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6675 }
6676 //81
6677 for(int32_t i=0; i<4; ++i)
6678 {
6679 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6680 }
6681 //85
6682 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6683 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6684 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6685 for(int32_t i=0; i<4; ++i)
6686 {
6687 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6688 }
6689 //91
6690 }
6691 if(!every_proc && !movelist->check_prot())
6692 return false;
6693 }
6694 //Map Styles
6695 {
6696 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6697 dest_process, source_process, mode,
6698 move
6699 ? "The tiles used by the following map styles will be partially cleared by the move."
6700 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6701 ));
6702 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6703 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6704 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6705 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6706 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6707 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6708 if(!every_proc && !movelist->check_prot())
6709 return false;
6710 }
6711 //Game Icons
6712 {
6713 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6714 dest_process, source_process, mode,
6715 move
6716 ? "The tiles used by the following game icons will be partially cleared by the move."
6717 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6718 ));
6719 for(int32_t u=0; u<4; u++)
6720 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6721 if(!every_proc && !movelist->check_prot())
6722 return false;
6723 }
6724 //DMaps
6725 {
6726 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6727 dest_process, source_process, mode,
6728 move
6729 ? "The tiles used by the following dmaps will be partially cleared by the move."
6730 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6731 ));
6732 for(int32_t u=0; u<MAXDMAPS; u++)
6733 {
6734 auto& dm = DMaps[u];
6735 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6736 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6737 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6738 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6739 }
6740 if(!every_proc && !movelist->check_prot())
6741 return false;
6742 }
6743 //Enemies
6744 {
6745 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6746 dest_process, source_process, mode,
6747 move
6748 ? "The tiles used by the following enemies will be partially cleared by the move."
6749 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6750 ));
6751 build_bie_list(false);
6752 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6753 for(int u=0; u<eMAXGUYS; u++)
6754 {
6755 guydata& enemy=guysbuf[bie[u].i];
6756 bool darknut=false;
6757 int32_t gleeok=0;
6758
6759 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6760 darknut=true;
6761 else if(enemy.family==eeGLEEOK)
6762 {
6763 // Not certain this is the right thing to check...
6764 if(enemy.attributes[2] == 0)
6765 gleeok=1;
6766 else
6767 gleeok=2;
6768 }
6769
6770 // Dummied out enemies
6771 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6772 {
6773 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6774 {
6775 continue;
6776 }
6777 }
6778
6779 if(newtiles)
6780 {
6781 if(guysbuf[bie[u].i].e_tile==0)
6782 {
6783 continue;
6784 }
6785
6786 vector<std::tuple<int,int,int>> rects;
6787
6788 if(darknut)
6789 {
6790 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6791 }
6792 else if(enemy.family==eeGANON)
6793 {
6794 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6795 }
6796 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6797 {
6798 for(int32_t j=0; j<4; ++j)
6799 {
6800 rects.emplace_back(
6801 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6802 4, 1);
6803 }
6804 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6805 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6806 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6807 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6808 }
6809 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6810 false, 0, 0, rects);
6811 }
6812 else
6813 {
6814 if(guysbuf[bie[u].i].tile==0)
6815 {
6816 continue;
6817 }
6818 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6819
6820 if(guysbuf[bie[u].i].s_tile!=0)
6821 {
6822 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6823 }
6824 }
6825 }
6826 if(!every_proc && !movelist->check_prot())
6827 return false;
6828 }
6829 //Subscreens
6830 {
6831 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6832 dest_process, source_process, mode,
6833 move
6834 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6835 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6836 ));
6837
6838 for(auto q = 0; q < subscreens_active.size(); ++q)
6839 {
6840 size_t indx = movelist->move_refs.size();
6841 subscreens_active[q].collect_tiles(*movelist.get());
6842 for(; indx < movelist->move_refs.size(); ++indx)
6843 {
6844 auto& ref = movelist->move_refs[indx];
6845 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6846 }
6847 }
6848 for(auto q = 0; q < subscreens_passive.size(); ++q)
6849 {
6850 size_t indx = movelist->move_refs.size();
6851 subscreens_passive[q].collect_tiles(*movelist.get());
6852 for(; indx < movelist->move_refs.size(); ++indx)
6853 {
6854 auto& ref = movelist->move_refs[indx];
6855 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6856 }
6857 }
6858 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6859 {
6860 size_t indx = movelist->move_refs.size();
6861 subscreens_overlay[q].collect_tiles(*movelist.get());
6862 for(; indx < movelist->move_refs.size(); ++indx)
6863 {
6864 auto& ref = movelist->move_refs[indx];
6865 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6866 }
6867 }
6868 if(!every_proc && !movelist->check_prot())
6869 return false;
6870 }
6871 //Strings
6872 {
6873 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6874 dest_process, source_process, mode,
6875 move
6876 ? "The tiles used by the following strings will be partially cleared by the move."
6877 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6878 ));
6879 for(size_t q = 0; q < msg_count; ++q)
6880 {
6881 MsgStr& str = MsgStrings[q];
6882 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6883 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6884 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6885 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6886 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6887 }
6888 if(!every_proc && !movelist->check_prot())
6889 return false;
6890 }
6891
6892 if(source_process) //Apply the 'diff' value to all moved tiles
6893 storage.redo();
6894 if(every_proc)
6895 for(auto &list : vec)
6896 for(auto &ref : list->move_refs)
6897 ref->forEach(every_proc);
6898 return true;
6899 }
6900 bool handle_tile_move(TileMoveProcess dest_process)
6901 {
6902 return _handle_tile_move(dest_process, nullopt, 0);
6903 }
6904 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6905 {
6906 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6907 }
6908 void for_every_used_tile(std::function<void(int32_t)> proc)
6909 {
6910 reset_combo_animations();
6911 reset_combo_animations2();
6912 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6913 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6914 }
6915
6916 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6917 {
6918 bool BSZ2 = get_qr(qr_BSZELDA);
6919 bool move = source_process.has_value();
6920 ComboMoveUndo local_undo;
6921 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6922 auto& vec = storage.vec;
6923 auto& combo_links = storage.combo_links;
6924 storage.diff = diff;
6925 storage.state = false;
6926 //Combo relative links
6927 {
6928 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6929 {
6930 newcombo& cmb = combobuf[q];
6931 if(cmb.trigchange)
6932 combo_links.add_to(q, q+cmb.trigchange);
6933 bool next = cmb.flag == mfSECRETSNEXT;
6934 switch(cmb.type)
6935 {
6936 case cPOUND:
6937 case cLOCKBLOCK: case cLOCKBLOCK2:
6938 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6939 case cCHEST: case cCHEST2:
6940 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6941 case cBOSSCHEST: case cBOSSCHEST2:
6942 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6943 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6944 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6945 case cTALLGRASSNEXT: case cCRUMBLE:
6946 next = true;
6947 break;
6948 case cCSWITCH: case cCSWITCHBLOCK:
6949 combo_links.add_to(q, q+cmb.attributes[0]);
6950 break;
6951 case cLIGHTTARGET:
6952 if(cmb.usrflags & cflag1)
6953 combo_links.add_to(q, q-1);
6954 else next = true;
6955 break;
6956 case cSTEPSFX:
6957 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6958 next = true;
6959 break;
6960 }
6961 if(next)
6962 combo_links.add_to(q, q+1);
6963 }
6964 }
6965
6966 //This function is expensive! Any optimizations possible should be made. -Em
6967
6968 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6969 #define ADDC(ptr, ...) \
6970 if(*ptr) movelist->add_combo(ptr, __VA_ARGS__);
6971 #define ADDC_10k(ptr, ...) \
6972 if(*ptr) movelist->add_combo_10k(ptr, __VA_ARGS__);
6973 //Combos
6974 {
6975 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6976 combo_links, dest_process, source_process,
6977 move
6978 ? "The combos used by the following combos will be partially cleared by the move."
6979 : "The combos used by the following combos will be partially or completely overwritten by this process."
6980 ));
6981 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6982 {
6983 newcombo& cmb = combobuf[q];
6984 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
6985 : fmt::format(" ({})", cmb.label));
6986 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
6987 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
6988 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
6989 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
6990
6991 //type-specific
6992 char const* type_name = ZI.getComboTypeName(cmb.type);
6993 switch(cmb.type)
6994 {
6995 case cLOCKEDCHEST: case cBOSSCHEST:
6996 if(cmb.usrflags & cflag13)
6997 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6998 [[fallthrough]];
6999 case cCHEST:
7000 if(cmb.usrflags & cflag13)
7001 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7002 break;
7003 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7004 if(cmb.usrflags & cflag13)
7005 {
7006 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7007 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7008 }
7009 break;
7010 case cSIGNPOST:
7011 if(cmb.usrflags & cflag13)
7012 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7013 break;
7014 case cBUTTONPROMPT:
7015 if(cmb.usrflags & cflag13)
7016 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7017 break;
7018 }
7019 }
7020
7021 if(!movelist->check_prot())
7022 return false;
7023 }
7024 //Door Combo Sets
7025 {
7026 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7027 combo_links, dest_process, source_process,
7028 move
7029 ? "The combos used by the following screens will be partially cleared by the move."
7030 : "The combos used by the following screens will be partially or completely overwritten by this process."
7031 ));
7032 static const char* door_names[9] = {
7033 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7034 };
7035 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7036 {
7037 auto& dcs = DoorComboSets[i];
7038 for(int32_t j=0; j<9; j++)
7039 {
7040 if(j<4)
7041 {
7042 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7043
7044 if(j<3)
7045 {
7046 if(j<2)
7047 {
7048 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7049 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7050 }
7051 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7052 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7053 }
7054 }
7055
7056 for(int32_t k=0; k<6; k++)
7057 {
7058 if(k<4)
7059 {
7060 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7061 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7062 }
7063
7064 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7065 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7066 }
7067 }
7068 }
7069
7070 if(!movelist->check_prot())
7071 return false;
7072 }
7073 //Combo Pools
7074 {
7075 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7076 combo_links, dest_process, source_process,
7077 move
7078 ? "The combos used by the following combo pools will be partially cleared by the move."
7079 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7080 ));
7081 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7082 {
7083 combo_pool& pool = combo_pools[q];
7084 int idx = 0;
7085 for(cpool_entry& cp : pool.combos)
7086 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7087 }
7088
7089 if(!movelist->check_prot())
7090 return false;
7091 }
7092 //Auto Combos
7093 {
7094 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7095 combo_links, dest_process, source_process,
7096 move
7097 ? "The combos used by the following autocombos will be partially cleared by the move."
7098 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7099 ));
7100 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7101 {
7102 combo_auto& cauto = combo_autos[q];
7103 int idx = 0;
7104 for (autocombo_entry& ac : cauto.combos)
7105 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7106 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7107 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7108 }
7109
7110 if(!movelist->check_prot())
7111 return false;
7112 }
7113 //Combo Aliases
7114 {
7115 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7116 combo_links, dest_process, source_process,
7117 move
7118 ? "The combos used by the following aliases will be partially cleared by the move."
7119 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7120 ));
7121 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7122 {
7123 //dimensions are 1 less than you would expect -DD
7124 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7125
7126 for(int32_t j=0; j<count; j++)
7127 {
7128 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7129 }
7130 }
7131
7132 if(!movelist->check_prot())
7133 return false;
7134 }
7135 //Favorite Combos
7136 {
7137 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7138 combo_links, dest_process, source_process,
7139 move
7140 ? "The combos used by the following favorite combos will be partially cleared by the move."
7141 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7142 ));
7143 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7144 {
7145 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7146 continue;
7147 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7148 }
7149
7150 if(!movelist->check_prot())
7151 return false;
7152 }
7153 //Bottle Shops
7154 {
7155 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7156 combo_links, dest_process, source_process,
7157 move
7158 ? "The combos used by the following bottle shops will be partially cleared by the move."
7159 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7160 ));
7161 for(auto q = 0; q < 256; ++q)
7162 for(auto p = 0; p < 3; ++p)
7163 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7164
7165 if(!movelist->check_prot())
7166 return false;
7167 }
7168 //Screens //EXPENSIVE! DO THIS LAST!
7169 {
7170 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7171 combo_links, dest_process, source_process,
7172 move
7173 ? "The combos used by the following screens will be partially cleared by the move."
7174 : "The combos used by the following screens will be partially or completely overwritten by this process."
7175 ));
7176
7177 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7178 {
7179 for(int32_t j=0; j<MAPSCRS; j++)
7180 {
7181 mapscr& scr = TheMaps[i*MAPSCRS+j];
7182
7183 if(!(scr.valid&mVALID))
7184 continue;
7185
7186 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7187 for(int32_t k=0; k<176; k++)
7188 ADDC(&scr.data[k], fmt::format("{}x{:02X} - Pos {}", i, j, k));
7189
7190 for(int32_t k=0; k<128; k++)
7191 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7192
7193 word maxffc = scr.numFFC();
7194 for(word k=0; k<maxffc; k++)
7195 {
7196 ffcdata& ffc = scr.ffcs[k];
7197 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7198 }
7199 }
7200 }
7201
7202 if(!movelist->check_prot())
7203 return false;
7204 }
7205 if(source_process) //Apply the 'diff' value to all moved combos
7206 storage.redo();
7207 return true;
7208 }
7209
7210 bool handle_combo_move(ComboMoveProcess dest_process)
7211 {
7212 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7213 }
7214 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7215 {
7216 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7217 }
7218 void register_used_tiles()
7219 {
7220 memset(used_tile_table, 0, sizeof(used_tile_table));
7221 for_every_used_tile([&](int tile)
7222 {
7223 used_tile_table[tile] = true;
7224 });
7225 }
7226
7227 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7228 {
7229 bool ctrl=(CHECK_CTRL_CMD);
7230 bool copied=false;
7231 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7232
7233 if(copied)
7234 {
7235 saved=false;
7236 }
7237
7238 return copied;
7239 }
7240
7241 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7242 {
7243 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7244 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7245
7246 // if tile>tile2 then swap them
7247 if(tile>tile2)
7248 {
7249 zc_swap(tile, tile2);
7250 }
7251
7252 // alt=copy from right
7253 // shift=copy from bottom
7254
7255 int32_t copies=copycnt;
7256 int32_t dest_first=tile;
7257 int32_t dest_last=tile2;
7258 int32_t src_first=copy;
7259 int32_t src_last=copy+copies-1;
7260
7261 int32_t dest_top=0;
7262 int32_t dest_bottom=0;
7263 int32_t src_top=0;
7264 int32_t src_bottom=0;
7265 int32_t src_left=0, src_right=0;
7266 int32_t src_width=0, src_height=0;
7267 int32_t dest_left=0, dest_right=0;
7268 int32_t dest_width=0, dest_height=0;
7269 int32_t rows=0, cols=0;
7270
7271 if(rect)
7272 {
7273 dest_top=TILEROW(dest_first);
7274 dest_bottom=TILEROW(dest_last);
7275 src_top=TILEROW(src_first);
7276 src_bottom=TILEROW(src_last);
7277
7278 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7279 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7280 src_first=(src_top * TILES_PER_ROW)+src_left;
7281 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7282
7283 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7284 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7285 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7286 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7287
7288 //if no dest range set, then set one
7289 if((dest_first==dest_last)&&(src_first!=src_last))
7290 {
7291 if(alt)
7292 {
7293 dest_left=dest_right-(src_right-src_left);
7294 }
7295 else
7296 {
7297 dest_right=dest_left+(src_right-src_left);
7298 }
7299
7300 if(shift)
7301 {
7302 dest_top=dest_bottom-(src_bottom-src_top);
7303 }
7304 else
7305 {
7306 dest_bottom=dest_top+(src_bottom-src_top);
7307 }
7308
7309 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7310 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7311 }
7312 else
7313 {
7314 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7315 {
7316 if(alt) //copy from right tile instead of left
7317 {
7318 src_left=src_right-(dest_right-dest_left);
7319 }
7320 else //copy from left tile
7321 {
7322 src_right=src_left+(dest_right-dest_left);
7323 }
7324 }
7325 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7326 {
7327 if(alt) //copy from right tile instead of left
7328 {
7329 dest_left=dest_right-(src_right-src_left);
7330 }
7331 else //copy from left tile
7332 {
7333 dest_right=dest_left+(src_right-src_left);
7334 }
7335 }
7336
7337 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7338 {
7339 if(shift) //copy from bottom tile instead of top
7340 {
7341 src_top=src_bottom-(dest_bottom-dest_top);
7342 }
7343 else //copy from top tile
7344 {
7345 src_bottom=src_top+(dest_bottom-dest_top);
7346 }
7347 }
7348 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7349 {
7350 if(shift) //copy from bottom tile instead of top
7351 {
7352 dest_top=dest_bottom-(src_bottom-src_top);
7353 }
7354 else //copy from top tile
7355 {
7356 dest_bottom=dest_top+(src_bottom-src_top);
7357 }
7358 }
7359
7360 src_first=(src_top * TILES_PER_ROW)+src_left;
7361 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7362 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7363 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7364 }
7365
7366 cols=src_right-src_left+1;
7367 rows=src_bottom-src_top+1;
7368
7369 dest_width=dest_right-dest_left+1;
7370 dest_height=dest_bottom-dest_top+1;
7371 src_width=src_right-src_left+1;
7372 src_height=src_bottom-src_top+1;
7373
7374 }
7375 else //!rect
7376 {
7377 //if no dest range set, then set one
7378 if((dest_first==dest_last)&&(src_first!=src_last))
7379 {
7380 if(alt)
7381 {
7382 dest_first=dest_last-(src_last-src_first);
7383 }
7384 else
7385 {
7386 dest_last=dest_first+(src_last-src_first);
7387 }
7388 }
7389 else
7390 {
7391 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7392 {
7393 if(alt) //copy from last tile instead of first
7394 {
7395 src_first=src_last-(dest_last-dest_first);
7396 }
7397 else //copy from first tile
7398 {
7399 src_last=src_first+(dest_last-dest_first);
7400 }
7401 }
7402 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7403 {
7404 if(alt) //copy from last tile instead of first
7405 {
7406 dest_first=dest_last-(src_last-src_first);
7407 }
7408 else //copy from first tile
7409 {
7410 dest_last=dest_first+(src_last-src_first);
7411 }
7412 }
7413 }
7414
7415 copies=dest_last-dest_first+1;
7416 }
7417
7418
7419
7420 char buf2[80], buf3[80], buf4[80];
7421 sprintf(buf2, " ");
7422 sprintf(buf3, " ");
7423 sprintf(buf4, " ");
7424
7425 // warn if range extends beyond last tile
7426 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7427
7428 if(dest_last>=NEWMAXTILES)
7429 {
7430 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7431 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7432 return false;
7433 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7434 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7435 // {
7436 // return false;
7437 // }
7438 }
7439
7440
7441 TileMoveUndo on_undo;
7442 // Overwrite warnings
7443 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7444 if(move)
7445 {
7446 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7447 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7448 return false;
7449 }
7450 else
7451 {
7452 if(!handle_tile_move(dest))
7453 return false;
7454 }
7455 // copy tiles and delete if needed (move)
7456
7457 {
7458 go_tiles();
7459
7460 int32_t diff=dest_first-src_first;
7461
7462 if(rect)
7463 {
7464 for(int32_t r=0; r<rows; ++r)
7465 {
7466 for(int32_t c=0; c<cols; ++c)
7467 {
7468 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7469 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7470
7471 if(dt>=NEWMAXTILES)
7472 continue;
7473
7474 overlay_tile(newtilebuf,dt,st,cs,backwards);
7475
7476 }
7477 }
7478 }
7479 else
7480 {
7481 for(int32_t c=0; c<copies; ++c)
7482 {
7483 int32_t dt=(dest_first+c);
7484 int32_t st=(src_first+c);
7485
7486 if(dt>=NEWMAXTILES)
7487 continue;
7488
7489 overlay_tile(newtilebuf,dt,st,cs,backwards);
7490
7491 if(move)
7492 {
7493 if(st<dest_first||st>(dest_first+c-1))
7494 reset_tile(newtilebuf, st, tf4Bit);
7495 }
7496 }
7497 }
7498 }
7499
7500 //now that tiles have moved, fix these buffers -DD
7501 register_blank_tiles();
7502 register_used_tiles();
7503
7504 if(move)
7505 last_tile_move_list = std::move(on_undo);
7506 return true;
7507 }
7508 //
7509 bool do_movetile_united(tile_move_data const& tmd)
7510 {
7511 char buf2[80], buf3[80], buf4[80];
7512 sprintf(buf2, " ");
7513 sprintf(buf3, " ");
7514 sprintf(buf4, " ");
7515
7516 // warn if range extends beyond last tile
7517 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7518
7519 if(tmd.dest_last>=NEWMAXTILES)
7520 {
7521 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7522 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7523 return false;
7524 }
7525
7526 TileMoveUndo on_undo;
7527 // Overwrite warnings
7528 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7529 if(tmd.move)
7530 {
7531 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7532 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7533 return false;
7534 }
7535 else
7536 {
7537 if(!handle_tile_move(dest))
7538 return false;
7539 }
7540
7541 // copy tiles and delete if needed (tmd.move)
7542 {
7543 go_tiles();
7544
7545 if(tmd.rect)
7546 {
7547 for(int32_t r=0; r<tmd.rows; ++r)
7548 {
7549 for(int32_t c=0; c<tmd.cols; ++c)
7550 {
7551 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7552 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7553
7554 if(dt>=NEWMAXTILES)
7555 continue;
7556
7557 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7558
7559 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7560 {
7561 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7562 }
7563
7564 if(tmd.move)
7565 {
7566 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7567 reset_tile(newtilebuf, st, tf4Bit);
7568 else
7569 {
7570 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7571 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7572 if(destLeft<=destRight)
7573 {
7574 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7575 reset_tile(newtilebuf, st, tf4Bit);
7576 }
7577 else // Wrapped around
7578 {
7579 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7580 reset_tile(newtilebuf, st, tf4Bit);
7581 }
7582 }
7583 }
7584 }
7585 }
7586 }
7587 else
7588 {
7589 for(int32_t c=0; c<tmd.copies; ++c)
7590 {
7591 int32_t dt=(tmd.dest_first+c);
7592 int32_t st=(tmd.src_first+c);
7593
7594 if(dt>=NEWMAXTILES)
7595 continue;
7596
7597 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7598
7599 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7600 {
7601 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7602 }
7603
7604 if(tmd.move)
7605 {
7606 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7607 reset_tile(newtilebuf, st, tf4Bit);
7608 }
7609 }
7610 }
7611 }
7612
7613 //now that tiles have moved, fix these buffers -DD
7614 register_blank_tiles();
7615 register_used_tiles();
7616
7617 if(tmd.move)
7618 last_tile_move_list = std::move(on_undo);
7619 return true;
7620 }
7621
7622 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7623 {
7624 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7625 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7626
7627 // if tile>tile2 then swap them
7628 if(tile>tile2)
7629 {
7630 zc_swap(tile, tile2);
7631 }
7632
7633 // alt=copy from right
7634 // shift=copy from bottom
7635 tile_move_data tmd;
7636
7637 tmd.copies=copycnt;
7638 tmd.dest_first=tile;
7639 tmd.dest_last=tile2;
7640 tmd.src_first=copy;
7641 tmd.src_last=copy+tmd.copies-1;
7642 tmd.rect = rect;
7643 tmd.move = move;
7644
7645 if(rect)
7646 {
7647 tmd.dest_top=TILEROW(tmd.dest_first);
7648 tmd.dest_bottom=TILEROW(tmd.dest_last);
7649 tmd.src_top=TILEROW(tmd.src_first);
7650 tmd.src_bottom=TILEROW(tmd.src_last);
7651
7652 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7653 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7654 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7655 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7656
7657 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7658 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7659 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7660 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7661
7662 //if no dest range set, then set one
7663 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7664 {
7665 if(alt)
7666 {
7667 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7668 }
7669 else
7670 {
7671 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7672 }
7673
7674 if(shift)
7675 {
7676 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7677 }
7678 else
7679 {
7680 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7681 }
7682
7683 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7684 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7685 }
7686 else
7687 {
7688 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7689 {
7690 if(alt) //copy from right tile instead of left
7691 {
7692 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7693 }
7694 else //copy from left tile
7695 {
7696 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7697 }
7698 }
7699 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7700 {
7701 if(alt) //copy from right tile instead of left
7702 {
7703 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7704 }
7705 else //copy from left tile
7706 {
7707 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7708 }
7709 }
7710
7711 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7712 {
7713 if(shift) //copy from bottom tile instead of top
7714 {
7715 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7716 }
7717 else //copy from top tile
7718 {
7719 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7720 }
7721 }
7722 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7723 {
7724 if(shift) //copy from bottom tile instead of top
7725 {
7726 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7727 }
7728 else //copy from top tile
7729 {
7730 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7731 }
7732 }
7733
7734 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7735 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7736 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7737 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7738 }
7739
7740 tmd.cols=tmd.src_right-tmd.src_left+1;
7741 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7742
7743 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7744 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7745 tmd.src_width=tmd.src_right-tmd.src_left+1;
7746 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7747
7748 }
7749 else //!rect
7750 {
7751 //if no dest range set, then set one
7752 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7753 {
7754 if(alt)
7755 {
7756 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7757 }
7758 else
7759 {
7760 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7761 }
7762 }
7763 else
7764 {
7765 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7766 {
7767 if(alt) //copy from last tile instead of first
7768 {
7769 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7770 }
7771 else //copy from first tile
7772 {
7773 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7774 }
7775 }
7776 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7777 {
7778 if(alt) //copy from last tile instead of first
7779 {
7780 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7781 }
7782 else //copy from first tile
7783 {
7784 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7785 }
7786 }
7787 }
7788
7789 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7790 }
7791
7792 return do_movetile_united(tmd);
7793 }
7794
7795 //
7796
7797 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7798 {
7799 assert(!move); //not implemented
7800
7801 // if tile>tile2 then swap them
7802 if(tile>tile2)
7803 {
7804 zc_swap(tile, tile2);
7805 }
7806
7807 tile_move_data tmd;
7808 tmd.copies=copycnt;
7809 tmd.dest_first=tile;
7810 tmd.dest_last=tile2;
7811 tmd.src_first=copy;
7812 tmd.src_last=copy+tmd.copies-1;
7813
7814
7815
7816 if(rect)
7817 {
7818 tmd.dest_top=TILEROW(tmd.dest_first);
7819 tmd.dest_bottom=TILEROW(tmd.dest_last);
7820 //tmd.src_top=TILEROW(tmd.src_first);
7821 //tmd.src_bottom=TILEROW(tmd.src_last);
7822
7823 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7824 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7825 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7826 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7827
7828 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7829 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7830 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7831 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7832
7833
7834
7835
7836 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7837 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7838
7839 tmd.cols=tmd.dest_width+1;
7840 tmd.rows=tmd.dest_height+1;
7841
7842 al_trace("tmd.rows: %d\n", tmd.rows);
7843 al_trace("tmd.cols: %d\n", tmd.cols);
7844
7845
7846 }
7847 else //!rect
7848 {
7849 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7850 }
7851
7852
7853
7854 char buf2[80], buf3[80], buf4[80];
7855 sprintf(buf2, " ");
7856 sprintf(buf3, " ");
7857 sprintf(buf4, " ");
7858
7859 // warn if range extends beyond last tile
7860 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7861
7862 if(tmd.dest_last>=NEWMAXTILES)
7863 {
7864 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7865 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7866 return false;
7867 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7868 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7869 // {
7870 // return false;
7871 // }
7872 }
7873
7874 TileMoveUndo on_undo;
7875 // Overwrite warnings
7876 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7877 if(tmd.move)
7878 {
7879 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7880 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7881 return false;
7882 }
7883 else
7884 {
7885 if(!handle_tile_move(dest))
7886 return false;
7887 }
7888
7889 // copy tiles and delete if needed (move)
7890
7891 {
7892 go_tiles();
7893
7894 int32_t diff=tmd.dest_first-tmd.src_first;
7895
7896 if(rect)
7897 {
7898 al_trace("floodfill, rect\n");
7899 al_trace("tmd.rows: %d\n", tmd.rows);
7900 al_trace("tmd.cols: %d\n", tmd.cols);
7901 for(int32_t r=0; r<tmd.rows; ++r)
7902 {
7903 for(int32_t c=0; c<tmd.cols; ++c)
7904 {
7905 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7906 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7907
7908 if(dt>=NEWMAXTILES)
7909 continue;
7910
7911 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7912
7913 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7914 {
7915 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7916 }
7917 }
7918 }
7919 }
7920 else
7921 {
7922 for(int32_t c=0; c<tmd.copies; ++c)
7923 {
7924 int32_t dt=(tmd.dest_first+c);
7925 int32_t st=(tmd.src_first+c);
7926
7927 if(dt>=NEWMAXTILES)
7928 continue;
7929
7930 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7931
7932 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7933 {
7934 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7935 }
7936
7937 }
7938 }
7939 }
7940
7941 //now that tiles have moved, fix these buffers -DD
7942 register_blank_tiles();
7943 register_used_tiles();
7944
7945 if(tmd.move)
7946 last_tile_move_list = std::move(on_undo);
7947 return true;
7948 }
7949 //
7950
7951 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7952 {
7953 al_trace("Floodfill Psste\n");
7954 bool ctrl=(CHECK_CTRL_CMD);
7955 bool copied=false;
7956 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7957
7958 if(copied)
7959 {
7960 if(!ctrl)
7961 {
7962 copy=-1;
7963 tile2=tile;
7964 }
7965
7966 saved=false;
7967 }
7968
7969 return copied;
7970 }
7971
7972 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7973 {
7974 bool ctrl=(CHECK_CTRL_CMD);
7975 bool copied=false;
7976 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7977
7978 if(copied)
7979 {
7980 if(!ctrl)
7981 {
7982 copy=-1;
7983 tile2=tile;
7984 }
7985
7986 saved=false;
7987 }
7988
7989 return copied;
7990 }
7991
7992 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
7993 {
7994 // if tile>tile2 then swap them
7995 if(tile>tile2)
7996 {
7997 zc_swap(tile, tile2);
7998 }
7999 int32_t src_top = TILEROW(tile);
8000 int32_t src_bottom = TILEROW(tile2);
8001 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8002 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8003 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8004 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8005
8006 int32_t src_width = src_right-src_left+1,
8007 src_height = src_bottom-src_top+1;
8008 int32_t dest_width = src_width, dest_height = src_height;
8009 zfix dest_rot = 0_zf;
8010 if(rotate)
8011 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8012 else
8013 ScaleTileDialog(&dest_width, &dest_height).show();
8014 if (rotate)
8015 {
8016 if (dest_rot == 0) return false;
8017 }
8018 else
8019 {
8020 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8021 }
8022 dest_width = vbound(dest_width, 1, 20);
8023 dest_height = vbound(dest_height, 1, 20);
8024
8025 int32_t dest_top = src_top;
8026 int32_t dest_bottom = src_top+dest_height-1;
8027 int32_t dest_left = src_left;
8028 int32_t dest_right = src_left+dest_width-1;
8029 int32_t dest_first = src_first;
8030 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8031
8032
8033 if(dest_last>=NEWMAXTILES)
8034 {
8035 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8036 return false;
8037 }
8038
8039 // Overwrite warnings
8040 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8041 return false;
8042
8043 //Do the rotate
8044 {
8045 go_tiles();
8046
8047 int32_t diff=dest_first-src_first;
8048 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8049 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8050 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8051 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8052 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8053 if (rotate)
8054 {
8055 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8056 }
8057 else
8058 {
8059 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8060 0, 0, destbmp->w, destbmp->h);
8061 }
8062 int32_t mhei = zc_max(src_height,dest_height),
8063 mwid = zc_max(src_width, dest_width);
8064 for(int32_t r=0; r<mhei; ++r)
8065 {
8066 for(int32_t c=0; c<mwid; ++c)
8067 {
8068 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8069
8070 if(dt>=NEWMAXTILES)
8071 continue;
8072 if(r < dest_height && c < dest_width)
8073 {
8074 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8075 }
8076 else reset_tile(newtilebuf, dt, tf4Bit);
8077 }
8078 }
8079 }
8080
8081 register_blank_tiles();
8082 register_used_tiles();
8083 return true;
8084 }
8085
8086 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8087 {
8088 //these 2 shouldn't be needed, but just to be safe...
8089 reset_combo_animations();
8090 reset_combo_animations2();
8091
8092 if(tile2<tile)
8093 {
8094 zc_swap(tile,tile2);
8095 }
8096
8097 auto first = tile;
8098 auto last = masscopy ? tile2 : first + copycnt-1;
8099 if(!handle_combo_move({first,last}))
8100 return;
8101
8102 if(!masscopy)
8103 {
8104 if(tile==copy)
8105 {
8106 copy=-1;
8107 tile2=tile;
8108 return;
8109 }
8110
8111 // go_combos(); // commented because caller does it for us
8112 //if copying to an earlier combo, copy from left to right
8113 //otherwise, copy from right to left
8114 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8115 {
8116 if(tile+t < MAXCOMBOS)
8117 {
8118 combobuf[tile+t]=combobuf[copy+t];
8119 }
8120 }
8121
8122 copy=-1;
8123 tile2=tile;
8124 saved=false;
8125 }
8126 else
8127 {
8128 // go_combos();
8129 int32_t src=copy, dest=tile;
8130
8131 do
8132 {
8133 combobuf[dest]=combobuf[src];
8134 ++src;
8135 ++dest;
8136
8137 if((src-copy)==copycnt) src=copy;
8138 }
8139 while(dest<=tile2);
8140
8141 copy=-1;
8142 tile2=tile;
8143 saved=false;
8144 }
8145
8146 setup_combo_animations();
8147 setup_combo_animations2();
8148 }
8149
8150 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8151 {
8152 reset_combo_animations();
8153 reset_combo_animations2();
8154 go_combos();
8155
8156 auto diff = cmd.tile - cmd.copy1;
8157 if(is_undoing)
8158 on_undo.undo();
8159 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8160 return false;
8161
8162 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8163 {
8164 if(cmd.tile+t < MAXCOMBOS)
8165 {
8166 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8167 clear_combo(cmd.copy1+t);
8168 }
8169 }
8170
8171 setup_combo_animations();
8172 setup_combo_animations2();
8173 saved=false;
8174 return true;
8175 }
8176
8177 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8178 {
8179 if(tile2<tile)
8180 {
8181 zc_swap(tile,tile2);
8182 }
8183
8184 if(tile==copy)
8185 {
8186 copy=-1;
8187 tile2=tile;
8188 return;
8189 }
8190
8191 combo_move_data cmd;
8192 cmd.tile = tile;
8193 cmd.tile2 = tile2;
8194 cmd.copy1 = copy;
8195 cmd.copycnt = copycnt;
8196
8197 ComboMoveUndo on_undo;
8198 if(!do_movecombo(cmd, on_undo))
8199 return;
8200 last_combo_move_list = std::move(on_undo);
8201 copy=-1;
8202 tile2=tile;
8203 }
8204
8205 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8206 {
8207 if(firsttile > lasttile)
8208 zc_swap(firsttile,lasttile);
8209 int32_t coldiff = 0;
8210 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8211 {
8212 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8213 firsttile-=coldiff;
8214 lasttile+=coldiff;
8215 }
8216 for(int32_t t=firsttile; t<=lasttile; ++t)
8217 if(!rect_sel ||
8218 ((TILECOL(t)>=TILECOL(firsttile)) &&
8219 (TILECOL(t)<=TILECOL(lasttile))))
8220 reset_tile(newtilebuf, t, tf4Bit);
8221 saved=false;
8222 register_blank_tiles();
8223 }
8224
8225 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8226 {
8227 char buf[40];
8228
8229 if(tile==tile2)
8230 {
8231 sprintf(buf,"Delete tile %d?",tile);
8232 }
8233 else
8234 {
8235 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8236 }
8237
8238 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8239 {
8240 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8241
8242 go_tiles();
8243
8244 //if copying to an earlier tile, copy from left to right
8245 //otherwise, copy from right to left
8246 do_delete_tiles(firsttile, lasttile, rect_sel);
8247
8248 tile=tile2=zc_min(tile,tile2);
8249 saved=false;
8250 register_blank_tiles();
8251 }
8252 }
8253
8254 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8255 {
8256 byte buf[256];
8257 go_tiles();
8258
8259 unpack_tile(newtilebuf, dest, 0, false);
8260
8261 for(int32_t i=0; i<256; i++)
8262 buf[i] = unpackbuf[i];
8263
8264 unpack_tile(newtilebuf, src, 0, false);
8265
8266 if(newtilebuf[src].format>tf4Bit)
8267 {
8268 cs=0;
8269 }
8270
8271 cs &= 15;
8272 cs <<= CSET_SHFT;
8273
8274 for(int32_t i=0; i<256; i++)
8275 {
8276 if(backwards)
8277 {
8278 if(!buf[i])
8279 {
8280 buf[i] = unpackbuf[i]+cs;
8281 }
8282 }
8283 else
8284 {
8285 if(unpackbuf[i])
8286 {
8287 buf[i] = unpackbuf[i]+cs;
8288 }
8289 }
8290 }
8291
8292 pack_tile(newtilebuf, buf,dest);
8293 saved=false;
8294 }
8295
8296 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8297 {
8298 //byte buf[256];
8299 go_tiles();
8300
8301 if(!rect_sel)
8302 {
8303 for(int32_t d=dest1; d <= dest2; ++d)
8304 {
8305 /*unpack_tile(newtilebuf, d, 0, false);
8306
8307 for(int32_t i=0; i<256; i++)
8308 {
8309 if(!backwards)
8310 {
8311 if(!buf[i])
8312 {
8313 buf[i] = unpackbuf[i] + cs;
8314 }
8315 }
8316 else
8317 {
8318 if(unpackbuf[i])
8319 {
8320 buf[i] = unpackbuf[i] + cs;
8321 }
8322 }
8323 }
8324
8325 pack_tile(newtilebuf, buf,d);
8326 */
8327
8328 overlay_tile(newtilebuf,d,src,cs,backwards);
8329
8330 if(!blank_tile_table[src])
8331 {
8332 blank_tile_table[d]=false;
8333 }
8334 }
8335 }
8336 else
8337 {
8338 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8339 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8340 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8341 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8342 int32_t d=0;
8343
8344 for(int32_t j=cmin; j<=cmax; ++j)
8345 {
8346 for(int32_t k=rmin; k<=rmax; ++k)
8347 {
8348 d=j+TILES_PER_ROW*k;
8349 /*unpack_tile(newtilebuf, d, 0, false);
8350
8351 for(int32_t i=0; i<256; i++)
8352 {
8353 if(!backwards)
8354 {
8355 if(!buf[i])
8356 {
8357 buf[i] = unpackbuf[i] + cs;
8358 }
8359 }
8360 else
8361 {
8362 if(unpackbuf[i])
8363 {
8364 buf[i] = unpackbuf[i] + cs;
8365 }
8366 }
8367 }
8368
8369 pack_tile(newtilebuf, buf,d);
8370 */
8371
8372 overlay_tile(newtilebuf,d,src,cs,backwards);
8373
8374 if(!blank_tile_table[src])
8375 {
8376 blank_tile_table[d]=false;
8377 }
8378 }
8379 }
8380 }
8381
8382 return;
8383 }
8384
8385 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8386 {
8387 tile+=s;
8388 bound(tile,0,NEWMAXTILES-1);
8389
8390 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8391 tile2 = tile;
8392
8393 first = tile - (tile%TILES_PER_PAGE);
8394 }
8395
8396 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8397 {
8398 int32_t cst;
8399
8400 switch(bp2)
8401 {
8402 case tf4Bit:
8403 switch(newtilebuf[t].format)
8404 {
8405 case tf4Bit:
8406 //already in the right format
8407 break;
8408
8409 case tf8Bit:
8410 unpack_tile(newtilebuf, t, 0, true);
8411
8412 if(alt) //reduce
8413 {
8414 for(int32_t i=0; i<256; i++)
8415 {
8416 if(!shift||unpackbuf[i]!=0)
8417 {
8418 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8419 }
8420 }
8421 }
8422 else //truncate
8423 {
8424 for(int32_t i=0; i<256; i++)
8425 {
8426 unpackbuf[i]&=15;
8427 }
8428 }
8429
8430 reset_tile(newtilebuf, t, tf4Bit);
8431 pack_tile(newtilebuf, unpackbuf, t);
8432 break;
8433 }
8434
8435 break;
8436
8437 case tf8Bit:
8438 switch(newtilebuf[t].format)
8439 {
8440 case tf4Bit:
8441 unpack_tile(newtilebuf, t, 0, true);
8442 cst = cs&15;
8443 cst <<= CSET_SHFT;
8444
8445 for(int32_t i=0; i<256; i++)
8446 {
8447 if(!shift||unpackbuf[i]!=0)
8448 {
8449 unpackbuf[i]+=cst;
8450 }
8451 }
8452
8453 reset_tile(newtilebuf, t, tf8Bit);
8454 pack_tile(newtilebuf, unpackbuf, t);
8455 break;
8456
8457 case tf8Bit:
8458 //already in the right format
8459 break;
8460 }
8461
8462 break;
8463 }
8464 }
8465
8466 static DIALOG create_relational_tiles_dlg[] =
8467 {
8468 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8469 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8470 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8471 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8472 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8473 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8474 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8475 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8476 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8477 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8478 };
8479
8480 void draw_tile_list_window()
8481 {
8482 int32_t w = 640;
8483 int32_t h = 480;
8484
8485 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8486 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8487 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8488 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8489
8490 FONT *oldfont = font;
8491 font = get_zc_font(font_lfont);
8492 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8493 font=oldfont;
8494 return;
8495 }
8496
8497 void show_blank_tile(int32_t t)
8498 {
8499 char tbuf[80], tbuf2[80], tbuf3[80];
8500 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8501 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8502 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8503 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8504 }
8505
8506 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8507 {
8508 int num_bits;
8509 if (format == tf4Bit)
8510 num_bits = 4;
8511 else if (format == tf8Bit)
8512 num_bits = 8;
8513 else assert(false);
8514
8515 char buf[80];
8516 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8517
8518 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8519 {
8520 go_tiles();
8521 saved=false;
8522
8523 if(format == tf4Bit)
8524 {
8525 memset(cset_reduce_table, 0, 256);
8526 memset(col_diff,0,3*128);
8527 calc_cset_reduce_table(RAMpal, cs);
8528 }
8529
8530 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8531
8532 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8533 {
8534 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8535 firsttile-=coldiff;
8536 lasttile+=coldiff;
8537 }
8538
8539 for(int32_t t=firsttile; t<=lasttile; t++)
8540 if(!rect_sel ||
8541 ((TILECOL(t)>=TILECOL(firsttile)) &&
8542 (TILECOL(t)<=TILECOL(lasttile))))
8543 convert_tile(t, format, cs, shift, alt);
8544
8545 tile=tile2=zc_min(tile,tile2);
8546 }
8547 }
8548
8549
8550 int32_t readtilefile(PACKFILE *f)
8551 {
8552 dword section_version=0;
8553 dword section_cversion=0;
8554 int32_t zversion = 0;
8555 int32_t zbuild = 0;
8556
8557 if(!p_igetl(&zversion,f))
8558 {
8559 return 0;
8560 }
8561 if(!p_igetl(&zbuild,f))
8562 {
8563 return 0;
8564 }
8565 if(!p_igetw(&section_version,f))
8566 {
8567 return 0;
8568 }
8569 if(!p_igetw(&section_cversion,f))
8570 {
8571 return 0;
8572 }
8573 al_trace("readoneweapon section_version: %d\n", section_version);
8574 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8575
8576 if ( zversion > ZELDA_VERSION )
8577 {
8578 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8579 return 0;
8580 }
8581
8582 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8583 {
8584 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8585 return 0;
8586
8587 }
8588 else
8589 {
8590 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8591 }
8592
8593 int32_t index = 0;
8594 int32_t count = 0;
8595
8596 //tile id
8597 if(!p_igetl(&index,f))
8598 {
8599 return 0;
8600 }
8601 al_trace("Reading tile: index(%d)\n", index);
8602
8603 //tile count
8604 if(!p_igetl(&count,f))
8605 {
8606 return 0;
8607 }
8608 al_trace("Reading tile: count(%d)\n", count);
8609
8610
8611
8612
8613 for ( int32_t tilect = 0; tilect < count; tilect++ )
8614 {
8615 byte *temp_tile = new byte[tilesize(tf32Bit)];
8616 byte format=tf4Bit;
8617 memset(temp_tile, 0, tilesize(tf32Bit));
8618 if(!p_getc(&format,f))
8619 {
8620 delete[] temp_tile;
8621 return 0;
8622 }
8623
8624
8625 if(!pfread(temp_tile,tilesize(format),f))
8626 {
8627 delete[] temp_tile;
8628 return 0;
8629 }
8630
8631 reset_tile(newtilebuf, index+(tilect), format);
8632 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8633 delete[] temp_tile;
8634 }
8635
8636
8637 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8638
8639 register_blank_tiles();
8640 register_used_tiles();
8641
8642 return 1;
8643
8644 }
8645
8646 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8647 {
8648 dword section_version=0;
8649 dword section_cversion=0;
8650 int32_t zversion = 0;
8651 int32_t zbuild = 0;
8652
8653 if(!p_igetl(&zversion,f))
8654 {
8655 return 0;
8656 }
8657 if(!p_igetl(&zbuild,f))
8658 {
8659 return 0;
8660 }
8661 if(!p_igetw(&section_version,f))
8662 {
8663 return 0;
8664 }
8665 if(!p_igetw(&section_cversion,f))
8666 {
8667 return 0;
8668 }
8669 al_trace("readoneweapon section_version: %d\n", section_version);
8670 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8671
8672 if ( zversion > ZELDA_VERSION )
8673 {
8674 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8675 return 0;
8676 }
8677
8678 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8679 {
8680 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8681 return 0;
8682
8683 }
8684 else
8685 {
8686 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8687 }
8688
8689 int32_t index = 0;
8690 int32_t count = 0;
8691
8692 //tile id
8693 if(!p_igetl(&index,f))
8694 {
8695 return 0;
8696 }
8697 al_trace("Reading tile: index(%d)\n", index);
8698
8699 //tile count
8700 if(!p_igetl(&count,f))
8701 {
8702 return 0;
8703 }
8704 al_trace("Reading tile: count(%d)\n", count);
8705
8706
8707 for ( int32_t tilect = 0; tilect < count; tilect++ )
8708 {
8709 byte *temp_tile = new byte[tilesize(tf32Bit)];
8710 byte format=tf4Bit;
8711 memset(temp_tile, 0, tilesize(tf32Bit));
8712 if(!p_getc(&format,f))
8713 {
8714 delete[] temp_tile;
8715 return 0;
8716 }
8717
8718
8719 if(!pfread(temp_tile,tilesize(format),f))
8720 {
8721 delete[] temp_tile;
8722 return 0;
8723 }
8724
8725 reset_tile(newtilebuf, start+(tilect), format);
8726 if ( skip )
8727 {
8728 if ( (start+(tilect)) < skip )
8729 {
8730 delete[] temp_tile;
8731 continue;
8732 }
8733
8734 }
8735 if ( start+(tilect) < NEWMAXTILES )
8736 {
8737 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8738 }
8739 delete[] temp_tile;
8740
8741 }
8742
8743
8744 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8745
8746 register_blank_tiles();
8747 register_used_tiles();
8748
8749 return 1;
8750
8751 }
8752
8753
8754 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8755 {
8756 dword section_version=0;
8757 dword section_cversion=0;
8758 int32_t zversion = 0;
8759 int32_t zbuild = 0;
8760
8761 if(!p_igetl(&zversion,f))
8762 {
8763 return 0;
8764 }
8765 if(!p_igetl(&zbuild,f))
8766 {
8767 return 0;
8768 }
8769 if(!p_igetw(&section_version,f))
8770 {
8771 return 0;
8772 }
8773 if(!p_igetw(&section_cversion,f))
8774 {
8775 return 0;
8776 }
8777 al_trace("readoneweapon section_version: %d\n", section_version);
8778 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8779
8780 if ( zversion > ZELDA_VERSION )
8781 {
8782 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8783 return 0;
8784 }
8785
8786 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8787 {
8788 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8789 return 0;
8790
8791 }
8792 else
8793 {
8794 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8795 }
8796
8797 int32_t index = 0;
8798 int32_t count = 0;
8799
8800 //tile id
8801 if(!p_igetl(&index,f))
8802 {
8803 return 0;
8804 }
8805 al_trace("Reading tile: index(%d)\n", index);
8806
8807 //tile count
8808 if(!p_igetl(&count,f))
8809 {
8810 return 0;
8811 }
8812 al_trace("Reading tile: count(%d)\n", count);
8813
8814
8815
8816
8817 for ( int32_t tilect = 0; tilect < count; tilect++ )
8818 {
8819 byte *temp_tile = new byte[tilesize(tf32Bit)];
8820 byte format=tf4Bit;
8821 memset(temp_tile, 0, tilesize(tf32Bit));
8822
8823 if(!p_getc(&format,f))
8824 {
8825 delete[] temp_tile;
8826 return 0;
8827 }
8828
8829
8830 if(!pfread(temp_tile,tilesize(format),f))
8831 {
8832 delete[] temp_tile;
8833 return 0;
8834 }
8835
8836 reset_tile(newtilebuf, start+(tilect), format);
8837 if ( start+(tilect) < NEWMAXTILES )
8838 {
8839 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8840 }
8841 delete[] temp_tile;
8842 }
8843
8844
8845 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8846
8847 register_blank_tiles();
8848 register_used_tiles();
8849
8850 return 1;
8851
8852 }
8853 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8854 {
8855 dword section_version=V_TILES;
8856 dword section_cversion=CV_TILES;
8857 int32_t zversion = ZELDA_VERSION;
8858 int32_t zbuild = VERSION_BUILD;
8859
8860 if(!p_iputl(zversion,f))
8861 {
8862 return 0;
8863 }
8864 if(!p_iputl(zbuild,f))
8865 {
8866 return 0;
8867 }
8868 if(!p_iputw(section_version,f))
8869 {
8870 return 0;
8871 }
8872
8873 if(!p_iputw(section_cversion,f))
8874 {
8875 return 0;
8876 }
8877
8878 //start tile id
8879 if(!p_iputl(index,f))
8880 {
8881 return 0;
8882 }
8883
8884 //count
8885 if(!p_iputl(count,f))
8886 {
8887 return 0;
8888 }
8889
8890 for ( int32_t tilect = 0; tilect < count; tilect++ )
8891 {
8892 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8893 {
8894 return 0;
8895 }
8896 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8897 {
8898 return 0;
8899 }
8900 }
8901
8902 return 1;
8903
8904 }
8905
8906 static int32_t _selected_tile=-1, _selected_tcset=-1;
8907 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8908 {
8909 popup_zqdialog_start();
8910 reset_combo_animations();
8911 reset_combo_animations2();
8912 bound(tile,0,NEWMAXTILES-1);
8913 ex=exnow;
8914 int32_t done=0;
8915 int32_t oflip=flip;
8916 int32_t otile=tile;
8917 int32_t ocs=cs;
8918 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8919 int32_t copy=-1;
8920 int32_t tile2=tile,copycnt=0;
8921 int32_t tile_clicked=-1;
8922 bool rect_sel=true;
8923 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8924 position_mouse_z(0);
8925
8926 go();
8927
8928 register_used_tiles();
8929 int32_t w = 640;
8930 int32_t h = 480;
8931 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8932 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8933 int32_t screen_xofs=window_xofs+6;
8934 int32_t screen_yofs=window_yofs+25;
8935 int32_t panel_yofs=3;
8936 int32_t mul = 2;
8937 FONT *tfont = get_zc_font(font_lfont_l);
8938
8939 draw_tile_list_window();
8940 int32_t f=0;
8941 draw_tiles(first,cs,f);
8942
8943 if(type==0)
8944 {
8945 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8946 }
8947 else
8948 {
8949 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8950 }
8951
8952 go_tiles();
8953
8954 while(gui_mouse_b())
8955 {
8956 /* do nothing */
8957 rest(1);
8958 }
8959
8960 bool bdown=false;
8961
8962 #define FOREACH_START(_t) \
8963 { \
8964 int32_t _first, _last; \
8965 if(is_rect) \
8966 { \
8967 _first=top*TILES_PER_ROW+left; \
8968 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8969 } \
8970 else \
8971 { \
8972 _first=zc_min(tile, tile2); \
8973 _last=zc_max(tile, tile2); \
8974 } \
8975 for(int32_t _t=_first; _t<=_last; _t++) \
8976 { \
8977 if(is_rect) \
8978 { \
8979 int32_t row=TILEROW(_t); \
8980 if(row<top || row>=top+rows) \
8981 continue; \
8982 int32_t col=TILECOL(_t); \
8983 if(col<left || col>=left+columns) \
8984 continue; \
8985 } \
8986
8987 #define FOREACH_END\
8988 } \
8989 }
8990
8991 bool did_snap = false;
8992 int otl = tile, otl2 = tile2;
8993 do
8994 {
8995 HANDLE_CLOSE_ZQDLG();
8996 if(exiting_program) break;
8997 rest(4);
8998 int32_t top=TILEROW(zc_min(tile, tile2));
8999 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9000 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9001 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9002 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9003 bool redraw=false;
9004
9005 if(mouse_z!=0)
9006 {
9007 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9008 position_mouse_z(0);
9009 redraw=true;
9010 }
9011
9012 if(keypressed())
9013 {
9014 switch(readkey()>>8)
9015 {
9016 case KEY_ENTER_PAD:
9017 case KEY_ENTER:
9018 done=2;
9019 break;
9020
9021 case KEY_ESC:
9022 done=1;
9023 break;
9024
9025 case KEY_F1:
9026 onHelp();
9027 break;
9028
9029 case KEY_EQUALS:
9030 case KEY_PLUS_PAD:
9031 {
9032 if(CHECK_CTRL_CMD ||
9033 key[KEY_ALT] || key[KEY_ALTGR])
9034 {
9035 FOREACH_START(t)
9036 if(key[KEY_ALT] || key[KEY_ALTGR])
9037 shift_tile_colors(t, 16, false);
9038 else
9039 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9040 FOREACH_END
9041
9042 register_blank_tiles();
9043 }
9044 else if(edit_cs)
9045 cs = (cs<13) ? cs+1:0;
9046
9047 redraw=true;
9048 break;
9049 }
9050
9051 case KEY_Z:
9052 case KEY_F12:
9053 {
9054 if(!did_snap)
9055 {
9056 //Export tile page as screenshot
9057 PALETTE temppal;
9058 get_palette(temppal);
9059 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9060 draw_tiles(tempbmp,first,cs,f,false,true);
9061 save_bitmap(getSnapName(), tempbmp, RAMpal);
9062 destroy_bitmap(tempbmp);
9063
9064 redraw = true;
9065 did_snap = true;
9066 }
9067 break;
9068 }
9069
9070 case KEY_S:
9071 {
9072 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9073 break;
9074 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9075 if(!f) break;
9076 al_trace("Saving tile: %d\n", tile);
9077 writetilefile(f,tile,1);
9078 pack_fclose(f);
9079 break;
9080 }
9081 case KEY_L:
9082 {
9083 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9084 break;
9085 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9086 if(!f) break;
9087 al_trace("Saving tile: %d\n", tile);
9088 if (!readtilefile(f))
9089 {
9090 al_trace("Could not read from .ztile packfile %s\n", temppath);
9091 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9092 }
9093 else
9094 {
9095 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9096 }
9097
9098 pack_fclose(f);
9099 //register_blank_tiles();
9100 //register_used_tiles();
9101 redraw=true;
9102 break;
9103 }
9104 case KEY_MINUS:
9105 case KEY_MINUS_PAD:
9106 {
9107 if(CHECK_CTRL_CMD ||
9108 key[KEY_ALT] || key[KEY_ALTGR])
9109 {
9110 FOREACH_START(t)
9111 if(key[KEY_ALT] || key[KEY_ALTGR])
9112 shift_tile_colors(t, -16, false);
9113 else
9114 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9115 FOREACH_END
9116
9117 register_blank_tiles();
9118 }
9119 else if(edit_cs)
9120 cs = (cs>0) ? cs-1:13;
9121
9122 redraw=true;
9123 break;
9124 }
9125
9126 case KEY_UP:
9127 {
9128 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9129 {
9130 case 3: //ALT and CTRL
9131 case 2: //ALT
9132 if(is_rect)
9133 {
9134 saved=false;
9135 go_slide_tiles(columns, rows, top, left);
9136 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9137 bool same = true;
9138
9139 for(int32_t d=0; d<columns; d++)
9140 {
9141 for(int32_t s=0; s<rows; s++)
9142 {
9143 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9144
9145 if(newtilebuf[t].format!=bitcheck) same = false;
9146 }
9147 }
9148
9149 if(!same) break;
9150
9151 // This used to do something. Too lazy to remove.
9152 // Can probably remove the above "same" check too.
9153 bitcheck = 2;
9154
9155 for(int32_t c=0; c<columns; c++)
9156 {
9157 for(int32_t r=0; r<rows; r++)
9158 {
9159 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9160 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9161 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9162
9163 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9164 {
9165 if(pixelrow==15*bitcheck)
9166 {
9167 int32_t srctile=temptile+TILES_PER_ROW;
9168 if(srctile>=NEWMAXTILES)
9169 srctile-=rows*TILES_PER_ROW;
9170 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9171 }
9172
9173 *dest_pixelrow=*src_pixelrow;
9174 dest_pixelrow++;
9175 src_pixelrow++;
9176 }
9177 }
9178
9179 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9180
9181 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9182 {
9183 if((CHECK_CTRL_CMD))
9184 {
9185 *dest_pixelrow=0;
9186 }
9187 else
9188 {
9189 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9190 *dest_pixelrow=*src_pixelrow;
9191 }
9192 }
9193 }
9194 }
9195
9196 register_blank_tiles();
9197 redraw=true;
9198 break;
9199
9200 case 1: //CTRL
9201 case 0: //None
9202 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9203 redraw=true;
9204
9205 default: //Others
9206 break;
9207 }
9208 }
9209 break;
9210
9211 case KEY_DOWN:
9212 {
9213 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9214 {
9215 case 3: //ALT and CTRL
9216 case 2: //ALT
9217 if(is_rect)
9218 {
9219 saved=false;
9220 go_slide_tiles(columns, rows, top, left);
9221 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9222 bool same = true;
9223
9224 for(int32_t c=0; c<columns; c++)
9225 {
9226 for(int32_t r=0; r<rows; r++)
9227 {
9228 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9229
9230 if(newtilebuf[t].format!=bitcheck) same = false;
9231 }
9232 }
9233
9234 if(!same) break;
9235
9236 // This used to do something. Too lazy to remove.
9237 // Can probably remove the above "same" check too.
9238 bitcheck = 2;
9239
9240 for(int32_t c=0; c<columns; c++)
9241 {
9242 for(int32_t r=rows-1; r>=0; r--)
9243 {
9244 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9245 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9246 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9247
9248 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9249 {
9250 if(pixelrow<bitcheck)
9251 {
9252 int32_t srctile=temptile-TILES_PER_ROW;
9253 if(srctile<0)
9254 srctile+=rows*TILES_PER_ROW;
9255 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9256 *dest_pixelrow=*tempsrc;
9257 //*dest_pixelrow=0;
9258 }
9259 else
9260 {
9261 *dest_pixelrow=*src_pixelrow;
9262 }
9263
9264 dest_pixelrow--;
9265 src_pixelrow--;
9266 }
9267 }
9268
9269 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9270 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9271
9272 for(int32_t b=0; b<bitcheck; b++)
9273 {
9274 if((CHECK_CTRL_CMD))
9275 {
9276 *dest_pixelrow=0;
9277 }
9278 else
9279 {
9280 *dest_pixelrow=*src_pixelrow;
9281 }
9282
9283 dest_pixelrow++;
9284 src_pixelrow++;
9285 }
9286 }
9287 }
9288
9289 register_blank_tiles();
9290 redraw=true;
9291 break;
9292
9293 case 1: //CTRL
9294 case 0: //None
9295 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9296 redraw=true;
9297
9298 default: //Others
9299 break;
9300 }
9301 }
9302 break;
9303
9304 case KEY_LEFT:
9305 {
9306 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9307 {
9308 case 3: //ALT and CTRL
9309 case 2: //ALT
9310 if(is_rect)
9311 {
9312 saved=false;
9313 go_slide_tiles(columns, rows, top, left);
9314 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9315 bool same = true;
9316
9317 for(int32_t c=0; c<columns; c++)
9318 {
9319 for(int32_t r=0; r<rows; r++)
9320 {
9321 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9322
9323 if(newtilebuf[t].format!=bitcheck) same = false;
9324 }
9325 }
9326
9327 if(!same) break;
9328
9329 // This used to do something. Too lazy to remove.
9330 // Can probably remove the above "same" check too.
9331 bitcheck = 2;
9332
9333 for(int32_t r=0; r<rows; r++)
9334 {
9335 for(int32_t c=0; c<columns; c++)
9336 {
9337 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9338 byte *dest_pixelrow=(newtilebuf[temptile].data);
9339
9340 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9341 {
9342 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9343 {
9344 *dest_pixelrow=*(dest_pixelrow+1);
9345 dest_pixelrow++;
9346 }
9347
9348 if(c==columns-1)
9349 {
9350 if(!(CHECK_CTRL_CMD))
9351 {
9352 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9353 *dest_pixelrow=*tempsrc;
9354 }
9355 }
9356 else
9357
9358 {
9359 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9360 *dest_pixelrow=*tempsrc;
9361 }
9362
9363 dest_pixelrow++;
9364 }
9365 }
9366 }
9367
9368 register_blank_tiles();
9369 redraw=true;
9370 }
9371
9372 break;
9373
9374 case 1: //CTRL
9375 case 0: //None
9376 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9377 redraw=true;
9378
9379 default: //Others
9380 break;
9381 }
9382 }
9383 break;
9384
9385 case KEY_RIGHT:
9386 {
9387 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9388 {
9389 case 3: //ALT and CTRL
9390 case 2: //ALT
9391 if(is_rect)
9392 {
9393 saved=false;
9394 go_slide_tiles(columns, rows, top, left);
9395 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9396 bool same = true;
9397
9398 for(int32_t c=0; c<columns; c++)
9399 {
9400 for(int32_t r=0; r<rows; r++)
9401 {
9402 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9403
9404 if(newtilebuf[t].format!=bitcheck) same = false;
9405 }
9406 }
9407
9408 if(!same) break;
9409
9410 // This used to do something. Too lazy to remove.
9411 // Can probably remove the above "same" check too.
9412 bitcheck = 2;
9413
9414 for(int32_t r=0; r<rows; r++)
9415 {
9416 for(int32_t c=columns-1; c>=0; c--)
9417 {
9418 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9419 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9420
9421 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9422 {
9423 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9424 {
9425 *dest_pixelrow=*(dest_pixelrow-1);
9426 dest_pixelrow--;
9427 }
9428
9429 if(c==0)
9430 {
9431 if(!(CHECK_CTRL_CMD))
9432 {
9433 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9434 *dest_pixelrow=*tempsrc;
9435 }
9436 }
9437 else
9438 {
9439 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9440 *dest_pixelrow=*tempsrc;
9441 }
9442
9443 dest_pixelrow--;
9444 }
9445 }
9446 }
9447
9448 register_blank_tiles();
9449 redraw=true;
9450 }
9451
9452 break;
9453
9454 case 1: //CTRL
9455 case 0: //None
9456 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9457 redraw=true;
9458
9459 default: //Others
9460 break;
9461 }
9462 }
9463 break;
9464
9465 case KEY_PGUP:
9466 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9467 redraw=true;
9468 break;
9469
9470 case KEY_PGDN:
9471 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9472 redraw=true;
9473 break;
9474
9475 case KEY_HOME:
9476 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9477 redraw=true;
9478 break;
9479
9480 case KEY_END:
9481 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9482 redraw=true;
9483 break;
9484
9485 case KEY_P:
9486 {
9487 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9488
9489 if(whatPage >= 0)
9490 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9491
9492 break;
9493 }
9494
9495 case KEY_O:
9496 if(type==0 && copy>=0)
9497 {
9498 go_tiles();
9499
9500 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9501 {
9502 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9503 saved=false;
9504 }
9505 else
9506 {
9507 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9508 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9509 }
9510
9511 saved=false;
9512 redraw=true;
9513 }
9514
9515 break;
9516
9517 case KEY_E:
9518 if(type==0)
9519 {
9520 edit_tile(tile,flip,cs);
9521 draw_tile_list_window();
9522 redraw=true;
9523 }
9524
9525 break;
9526
9527 case KEY_G:
9528 if(type==0)
9529 {
9530 grab_tile(tile,cs);
9531 draw_tile_list_window();
9532 redraw=true;
9533 }
9534
9535 break;
9536
9537 case KEY_C:
9538 copy=zc_min(tile,tile2);
9539 copycnt=abs(tile-tile2)+1;
9540 redraw=true;
9541 break;
9542
9543 case KEY_X:
9544 if(type==2)
9545 {
9546 ex=(ex+1)%3;
9547 }
9548
9549 break;
9550
9551 //usetiles=true;
9552 case KEY_R:
9553 if(type==2)
9554 break;
9555 if(type==1)
9556 {
9557 flip = rotate_value(flip);
9558 redraw=true;
9559 break;
9560 }
9561
9562 go_tiles();
9563
9564 if(CHECK_CTRL_CMD)
9565 {
9566 bool go=false;
9567 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9568 go=true;
9569 else if(massRecolorSetup(cs))
9570 go=true;
9571
9572 if(go)
9573 {
9574 FOREACH_START(t)
9575 massRecolorApply(t);
9576 FOREACH_END
9577
9578 register_blank_tiles();
9579 }
9580 }
9581 else
9582 {
9583 FOREACH_START(t)
9584 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9585 FOREACH_END
9586 }
9587
9588 redraw=true;
9589 saved=false;
9590 break;
9591
9592 case KEY_SPACE:
9593 rect_sel=!rect_sel;
9594 copy=-1;
9595 redraw=true;
9596 break;
9597
9598 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9599 case KEY_H:
9600 flip^=1;
9601 go_tiles();
9602
9603 if(type==0)
9604 {
9605 normalize(tile,tile2,rect_sel,flip);
9606 flip=0;
9607 }
9608
9609 redraw=true;
9610 break;
9611
9612
9613 case KEY_V:
9614 if(copy==-1)
9615 {
9616 if(type!=2)
9617 {
9618 flip^=2;
9619 go_tiles();
9620
9621 if(type==0)
9622 {
9623 normalize(tile,tile2,rect_sel,flip);
9624 flip=0;
9625 }
9626 }
9627 }
9628 else
9629 {
9630 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9631 go_tiles();
9632 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9633 }
9634
9635 redraw=true;
9636 break;
9637
9638 case KEY_F:
9639 if(copy==-1)
9640 {
9641 break;
9642 }
9643 else
9644 {
9645 go_tiles();
9646 {
9647 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9648 }
9649 }
9650
9651 redraw=true;
9652 break;
9653
9654 case KEY_DEL:
9655 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9656 {
9657 bool warn = (rect_sel
9658 && ((tile/20)!=(tile2/20))
9659 && !(tile%20==0&&tile2%20==19));
9660 int32_t z=zc_min(tile,tile2);
9661 int32_t count = abs(tile-tile2) + 1;
9662 tile=z;
9663 tile2=NEWMAXTILES;
9664 copy = tile + count;
9665 copycnt = NEWMAXTILES-copy;
9666 char buf[64];
9667
9668 if(count>1)
9669 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9670 else
9671 sprintf(buf,"Remove tile %d?",tile);
9672
9673 AlertDialog("Remove Tiles", std::string(buf)
9674 +"\nThis will offset the tiles that follow!"
9675 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9676 [&](bool ret,bool)
9677 {
9678 if(ret)
9679 {
9680 go_tiles();
9681 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9682 {
9683 redraw=true;
9684 saved=false;
9685 }
9686 }
9687 }).show();
9688 }
9689 delete_tiles(tile,tile2,rect_sel);
9690 redraw=true;
9691 break;
9692
9693 case KEY_U:
9694 {
9695 if(CHECK_CTRL_CMD)
9696 {
9697 //Only toggle the first 2 bits!
9698 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9699 }
9700 else
9701 {
9702 comeback_tiles();
9703 }
9704
9705 redraw=true;
9706 }
9707 break;
9708
9709 case KEY_8:
9710 case KEY_8_PAD:
9711 hide_8bit_marker();
9712 break;
9713
9714 case KEY_I: //insert tiles
9715 if(type==0)
9716 {
9717 bool warn = (rect_sel
9718 && ((tile/20)!=(tile2/20))
9719 && !(tile%20==0&&tile2%20==19));
9720 int32_t z=zc_min(tile,tile2);
9721 int32_t count = abs(tile-tile2) + 1;
9722 tile=z;
9723 tile2=NEWMAXTILES;
9724 copy = tile + count;
9725 copycnt = NEWMAXTILES-copy;
9726
9727 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9728 {
9729 char buf[64];
9730
9731 if(count>1)
9732 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9733 else
9734 sprintf(buf,"Remove tile %d?",tile);
9735
9736 AlertDialog("Remove Tiles", std::string(buf)
9737 +"\nThis will offset the tiles that follow!"
9738 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9739 [&](bool ret,bool)
9740 {
9741 if(ret)
9742 {
9743 go_tiles();
9744 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9745 {
9746 redraw=true;
9747 saved=false;
9748 }
9749 }
9750 }).show();
9751 }
9752 else
9753 {
9754 char buf[64];
9755
9756 if(count>1)
9757 sprintf(buf,"Insert %d blank tiles?",count);
9758 else
9759 sprintf(buf,"Insert a blank tile?");
9760
9761 AlertDialog("Insert Tiles", std::string(buf)
9762 +"\nThis will offset the tiles that follow!"
9763 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9764 [&](bool ret,bool)
9765 {
9766 if(ret)
9767 {
9768 go_tiles();
9769 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9770 {
9771 redraw=true;
9772 saved=false;
9773 }
9774 }
9775 }).show();
9776 }
9777
9778 copy=-1;
9779 tile2=tile=z;
9780 }
9781 break;
9782 case KEY_M:
9783 if(type==0)
9784 {
9785 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9786 {
9787 go_tiles();
9788 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9789 saved=false;
9790 }
9791 else if(copy==-1)
9792 {
9793 // I don't know what this was supposed to be doing before.
9794 // It didn't work in anything like a sensible way.
9795 if(rect_sel)
9796 {
9797 make_combos_rect(top, left, rows, columns, cs);
9798 }
9799 else
9800 {
9801 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9802 }
9803 }
9804
9805 redraw=true;
9806 }
9807 break;
9808
9809 case KEY_D:
9810 {
9811 int32_t frames=1;
9812 char buf[80];
9813 sprintf(buf, "%d", frames);
9814 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9815 create_relational_tiles_dlg[2].dp=buf;
9816
9817 large_dialog(create_relational_tiles_dlg);
9818
9819 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9820
9821 if(ret==5)
9822 {
9823 frames=zc_max(atoi(buf),1);
9824 bool same = true;
9825 int32_t bitcheck=newtilebuf[tile].format;
9826
9827 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9828 {
9829 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9830 }
9831
9832 if(!same)
9833 {
9834 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9835 break;
9836 }
9837
9838 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9839 {
9840 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9841 break;
9842 }
9843
9844 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9845 {
9846 reset_tile(newtilebuf, tile+i, bitcheck);
9847 }
9848
9849 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9850 {
9851 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9852 {
9853 for(int32_t j=0; j<frames; ++j)
9854 {
9855 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9856 }
9857 }
9858 }
9859 else
9860 {
9861 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9862 {
9863 for(int32_t j=0; j<frames; ++j)
9864 {
9865 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9866 }
9867 }
9868 }
9869 }
9870 register_blank_tiles();
9871 register_used_tiles();
9872 redraw=true;
9873 saved=false;
9874 break;
9875 }
9876
9877 case KEY_B:
9878 {
9879 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9880 bool control=(CHECK_CTRL_CMD);
9881 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9882 int format = control ? tf4Bit : tf8Bit;
9883
9884 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9885 register_blank_tiles();
9886 }
9887 break;
9888 }
9889
9890 clear_keybuf();
9891 }
9892
9893 if(!(key[KEY_Z] || key[KEY_F12]))
9894 did_snap = false;
9895
9896 if(gui_mouse_b()&1)
9897 {
9898 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9899 {
9900 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9901 {
9902 done=1;
9903 }
9904 }
9905
9906 int32_t x=gui_mouse_x()-screen_xofs;
9907 int32_t y=gui_mouse_y()-screen_yofs;
9908
9909 if(y>=0 && y<208*mul)
9910 {
9911 x=zc_min(zc_max(x,0),(320*mul)-1);
9912 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9913
9914 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9915 {
9916 tile2=t;
9917 }
9918 else
9919 {
9920 tile=tile2=t;
9921 }
9922
9923 if(tile_clicked!=t)
9924 {
9925 dclick_status=DCLICK_NOT;
9926 }
9927 else if(dclick_status == DCLICK_AGAIN)
9928 {
9929 while(gui_mouse_b())
9930 {
9931 /* do nothing */
9932 rest(1);
9933 }
9934
9935 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9936 {
9937 dclick_status=DCLICK_NOT;
9938 }
9939 else
9940 {
9941 if(type==0)
9942 {
9943 edit_tile(tile,flip,cs);
9944 draw_tile_list_window();
9945 redraw=true;
9946 }
9947 else
9948 {
9949 done=2;
9950 }
9951 }
9952 }
9953
9954 tile_clicked=t;
9955 }
9956 else if(x>300*mul && !bdown)
9957 {
9958 if(y<224*mul && first>0)
9959 {
9960 first-=TILES_PER_PAGE;
9961 redraw=true;
9962 }
9963
9964 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9965 {
9966 first+=TILES_PER_PAGE;
9967 redraw=true;
9968 }
9969
9970 bdown=true;
9971 }
9972
9973 if(type==1||type==2)
9974 {
9975 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9976 done=1;
9977
9978 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9979 done=2;
9980 }
9981 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9982 {
9983 rect_sel=!rect_sel;
9984 copy=-1;
9985 redraw=true;
9986 }
9987 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9988 {
9989 FONT *tf = font;
9990 font = tfont;
9991
9992 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9993 {
9994 font = tf;
9995 grab_tile(tile,cs);
9996 draw_tile_list_window();
9997 position_mouse_z(0);
9998 redraw=true;
9999 }
10000
10001 font = tf;
10002 }
10003 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10004 {
10005 FONT *tf = font;
10006 font = tfont;
10007
10008 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10009 {
10010 font = tf;
10011 edit_tile(tile,flip,cs);
10012 draw_tile_list_window();
10013 redraw=true;
10014 }
10015
10016 font = tf;
10017 }
10018 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10019 {
10020 FONT *tf = font;
10021 font = tfont;
10022
10023 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10024 {
10025 std::string initial_path = "tileset.png";
10026 if (strlen(datapath))
10027 initial_path = fmt::format("{}/{}", datapath, initial_path);
10028 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10029 {
10030 PALETTE temppal;
10031 get_palette(temppal);
10032 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10033 draw_tiles(tempbmp,first,cs,f,false,true);
10034 save_bitmap(temppath, tempbmp, RAMpal);
10035 destroy_bitmap(tempbmp);
10036 }
10037 }
10038
10039 font = tf;
10040 }
10041 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10042 {
10043 FONT *tf = font;
10044 font = tfont;
10045
10046 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10047 {
10048 if(massRecolorSetup(cs))
10049 {
10050 go_tiles();
10051
10052 FOREACH_START(t)
10053 massRecolorApply(t);
10054 FOREACH_END
10055
10056 register_blank_tiles();
10057 }
10058 }
10059
10060 font = tf;
10061 }
10062 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10063 {
10064 FONT *tf = font;
10065 font = tfont;
10066
10067 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10068 {
10069 done=1;
10070 }
10071
10072 font = tf;
10073 }
10074
10075 bdown=true;
10076 }
10077
10078 bool r_click = false;
10079
10080 if(gui_mouse_b()&2 && !bdown && type==0)
10081 {
10082 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10083 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10084
10085 if(y>=0 && y<208*mul)
10086 {
10087 x=zc_min(zc_max(x,0),(320*mul)-1);
10088 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10089
10090 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10091 tile=tile2=t;
10092 }
10093
10094 bdown = r_click = true;
10095 f=8;
10096 }
10097
10098 if(gui_mouse_b()==0)
10099 bdown=false;
10100
10101 position_mouse_z(0);
10102
10103 REDRAW:
10104
10105 if((f%8)==0 || InvalidBG == 1)
10106 redraw=true;
10107 if(otl != tile || otl2 != tile2)
10108 {
10109 otl = tile;
10110 otl2 = tile2;
10111 redraw = true;
10112 }
10113
10114 if(redraw)
10115 {
10116 draw_tiles(first,cs,f);
10117 }
10118 if(f&8)
10119 {
10120 if(rect_sel)
10121 {
10122 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10123 zc_min(TILECOL(tile),TILECOL(tile2));
10124 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10125 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10126 {
10127 if(i>=first && i<first+TILES_PER_PAGE &&
10128 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10129 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10130 {
10131 int32_t x=TILECOL(i)<<(5);
10132 int32_t y=TILEROW(i-first)<<(5);
10133 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10134 }
10135 }
10136 }
10137 else
10138 {
10139 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10140 {
10141 if(i>=first && i<first+TILES_PER_PAGE)
10142 {
10143 int32_t x=TILECOL(i)<<(5);
10144 int32_t y=TILEROW(i-first)<<(5);
10145 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10146 }
10147 }
10148 }
10149 }
10150
10151 if(type==0)
10152 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10153 else
10154 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10155
10156 if(type==2)
10157 {
10158 char cbuf[16];
10159 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10160 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10161 }
10162
10163 ++f;
10164
10165 if(r_click)
10166 {
10167 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10168 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10169 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10170 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10171
10172 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10173 if (newtilebuf[tile].format == tf8Bit)
10174 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10175 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10176 select_tile_color_depth_cb = [&](int format){
10177 if (newtilebuf[tile].format == format)
10178 return;
10179
10180 bool skip_prompt = true;
10181 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10182 };
10183
10184 NewMenu rcmenu
10185 {
10186 { "Copy", [&]()
10187 {
10188 copy = zc_min(tile,tile2);
10189 copycnt = abs(tile-tile2)+1;
10190 } },
10191 { "Paste", [&]()
10192 {
10193 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10194 if(saved) saved = !b;
10195 }, nullopt, copy < 0 },
10196 { "Move", [&]()
10197 {
10198 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10199 if(saved) saved = !b;
10200 }, nullopt, copy < 0 },
10201 { "Clear", [&]()
10202 {
10203 delete_tiles(tile, tile2, rect_sel);
10204 } },
10205 {},
10206 { "Edit", [&]()
10207 {
10208 edit_tile(tile, flip, cs);
10209 draw_tile_list_window();
10210 } },
10211 { "Grab", [&]()
10212 {
10213 grab_tile(tile, cs);
10214 draw_tile_list_window();
10215 position_mouse_z(0);
10216 } },
10217 { "Scale", [&]()
10218 {
10219 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10220 if(saved) saved = !b;
10221 }, nullopt, type != 0 },
10222 { "Angular Rotation", [&]()
10223 {
10224 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10225 if(saved) saved = !b;
10226 }, nullopt, type != 0 },
10227 { "Color Depth", &select_tile_color_depth_menu },
10228 {},
10229 { "Blank?", [&]()
10230 {
10231 show_blank_tile(tile);
10232 } },
10233 {},
10234 { "View ", &select_tile_view_menu },
10235 { "Overlay", [&]()
10236 {
10237 overlay_tile(newtilebuf, tile, copy, cs, 0);
10238 } },
10239 { "H-Flip", [&]()
10240 {
10241 flip ^= 1;
10242 go_tiles();
10243
10244 if(type == 0)
10245 {
10246 normalize(tile, tile2, rect_sel, flip);
10247 flip = 0;
10248 }
10249 } },
10250 { "V-Flip", [&]()
10251 {
10252 flip ^= 2;
10253 go_tiles();
10254
10255 if(type == 0)
10256 {
10257 normalize(tile, tile2, rect_sel, flip);
10258 flip = 0;
10259 }
10260 } },
10261 { "Create Combos", [&]()
10262 {
10263 if(rect_sel)
10264 make_combos_rect(top, left, rows, columns, cs);
10265 else
10266 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10267 }, nullopt, type != 0 },
10268 { "Insert", [&]()
10269 {
10270 bool warn = (rect_sel
10271 && ((tile/20)!=(tile2/20))
10272 && !(tile%20==0&&tile2%20==19));
10273 int32_t z = zc_min(tile, tile2);
10274 int32_t count = abs(tile-tile2) + 1;
10275 tile = z;
10276 tile2 = NEWMAXTILES;
10277 copy = tile + count;
10278 copycnt = NEWMAXTILES-copy;
10279
10280 string msg;
10281
10282 if(count>1)
10283 msg = fmt::format("Insert {} blank tiles?",count);
10284 else
10285 msg = "Insert a blank tile?";
10286
10287 AlertDialog("Insert Tiles", msg
10288 +"\nThis will offset the tiles that follow!"
10289 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10290 [&](bool ret,bool)
10291 {
10292 if(ret)
10293 {
10294 go_tiles();
10295 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10296 saved = false;
10297 }
10298 }).show();
10299
10300 copy=-1;
10301 tile2=tile=z;
10302 }, nullopt, type != 0 },
10303 { "Remove", [&]()
10304 {
10305 bool warn = (rect_sel
10306 && ((tile/20)!=(tile2/20))
10307 && !(tile%20==0&&tile2%20==19));
10308 int32_t z = zc_min(tile, tile2);
10309 int32_t count = abs(tile-tile2) + 1;
10310 tile = z;
10311 tile2 = NEWMAXTILES;
10312 copy = tile + count;
10313 copycnt = NEWMAXTILES-copy;
10314
10315 string msg;
10316
10317 if(count>1)
10318 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10319 else
10320 msg = fmt::format("Remove tile {}?", tile);
10321
10322 AlertDialog("Remove Tiles", msg
10323 +"\nThis will offset the tiles that follow!"
10324 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10325 [&](bool ret,bool)
10326 {
10327 if(ret)
10328 {
10329 go_tiles();
10330 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10331 saved = false;
10332 }
10333 }).show();
10334
10335 copy=-1;
10336 tile2=tile=z;
10337 }, nullopt, type != 0 },
10338 };
10339 rcmenu.pop(window_mouse_x(),window_mouse_y());
10340 redraw = true;
10341 r_click = false;
10342 goto REDRAW;
10343 }
10344 update_hw_screen();
10345 }
10346 while(!done);
10347
10348 while(gui_mouse_b())
10349 {
10350 /* do nothing */
10351 rest(1);
10352 }
10353
10354 comeback();
10355 register_blank_tiles();
10356 register_used_tiles();
10357 setup_combo_animations();
10358 setup_combo_animations2();
10359 int32_t ret = done-1;
10360 if(ret)
10361 {
10362 _selected_tile = tile;
10363 _selected_tcset = cs;
10364 }
10365
10366 popup_zqdialog_end();
10367 return ret;
10368 }
10369 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10370 {
10371 if(_selected_tile > -1)
10372 {
10373 tile = _selected_tile;
10374 cs = _selected_tcset;
10375 }
10376 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10377 if(_selected_tile < 0)
10378 {
10379 _selected_tile = tile;
10380 _selected_tcset = cs;
10381 }
10382 return ret;
10383 }
10384
10385 int32_t onTiles()
10386 {
10387 return onGotoTiles(-1);
10388 }
10389
10390 int32_t onGotoTiles(int32_t startfrom)
10391 {
10392 static int32_t t = 0;
10393 if (startfrom > -1)
10394 t = startfrom;
10395 int32_t f = 0;
10396 int32_t c = CSet;
10397 reset_pal_cycling();
10398 // loadlvlpal(Map.CurrScr()->color);
10399 rebuild_trans_table();
10400 select_tile(t, f, 0, c, true);
10401 refresh(rALL);
10402 return D_O_K;
10403 }
10404
10405 int32_t combopage_animate = 1;
10406 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10407 {
10408 if(unsigned(c)<MAXCOMBOS)
10409 {
10410 newcombo& cmb = combobuf[c];
10411 int t = cmb.tile;
10412 if(!animate)
10413 cmb.tile = cmb.o_tile;
10414 put_combo(dest,x,y,c,cs,0,0);
10415 cmb.tile = t;
10416 }
10417 else
10418 {
10419 rectfill(dest,x,y,x+32-1,y+32-1,0);
10420 }
10421 }
10422
10423 void draw_combos(int32_t page,int32_t cs,bool cols)
10424 {
10425 clear_bitmap(screen2);
10426 BITMAP *buf = create_bitmap_ex(8,16,16);
10427
10428 int32_t w = 32;
10429 int32_t h = 32;
10430 int32_t mul = 2;
10431
10432 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10433 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10434 int32_t screen_xofs=window_xofs+6;
10435 int32_t screen_yofs=window_yofs+25;
10436
10437 if(cols==false)
10438 {
10439 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10440 {
10441 int32_t x = (i%COMBOS_PER_ROW)*w;
10442 int32_t y = (i/COMBOS_PER_ROW)*h;
10443
10444 combotile_override_x = x+screen_xofs+(w-16)/2;
10445 combotile_override_y = y+screen_yofs+(h-16)/2;
10446 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10447 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10448 }
10449 }
10450 else
10451 {
10452 int32_t c = 0;
10453
10454 for(int32_t i=0; i<256; i++)
10455 {
10456 int32_t x = (i%COMBOS_PER_ROW)*w;
10457 int32_t y = (i/COMBOS_PER_ROW)*h;
10458
10459 combotile_override_x = x+screen_xofs+(w-16)/2;
10460 combotile_override_y = y+screen_yofs+(h-16)/2;
10461 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10462 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10463 ++c;
10464
10465 if((i&3)==3)
10466 c+=48;
10467
10468 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10469 c-=256;
10470 }
10471 }
10472 combotile_override_x = combotile_override_y = -1;
10473
10474 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10475 {
10476 vline(screen2,x,0,(208*mul)-1,vc(15));
10477 }
10478
10479 destroy_bitmap(buf);
10480 }
10481
10482 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10483 {
10484 int32_t yofs=3;
10485 static BITMAP *buf = create_bitmap_ex(8,16,16);
10486 int32_t mul = 2;
10487 FONT *tfont = get_zc_font(font_lfont_l);
10488
10489 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10490 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10491 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10492
10493 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10494
10495 if(copy>=0)
10496 {
10497 put_combo(buf,0,0,copy,cs,0,0);
10498 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10499
10500 if(copycnt>1)
10501 {
10502 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10503 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10504 }
10505 else
10506 {
10507 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10508 }
10509 }
10510 else
10511 {
10512 if (InvalidBG == 2)
10513 {
10514 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10515 }
10516 else if(InvalidBG == 1)
10517 {
10518 for(int32_t dy=0; dy<16*mul; dy++)
10519 {
10520 for(int32_t dx=0; dx<16*mul; dx++)
10521 {
10522 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10523 }
10524 }
10525 }
10526 else
10527 {
10528 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10529 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10530 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10531 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10532 }
10533 }
10534
10535 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10536 put_combo(buf,0,0,tile,cs,0,0);
10537 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10538
10539 if(tile>tile2)
10540 {
10541 zc_swap(tile,tile2);
10542 }
10543
10544 char cbuf[8];
10545 cbuf[0]=0;
10546
10547 if(tile2!=tile)
10548 {
10549 sprintf(cbuf,"-%d",tile2);
10550 }
10551
10552 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10553 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10554
10555 if(tile2==tile)
10556 {
10557 int32_t nextcombo=combobuf[tile].nextcombo;
10558 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10559 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10560
10561 if(nextcombo>0)
10562 {
10563 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10564 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10565 }
10566 else
10567 {
10568 if (InvalidBG == 2)
10569 {
10570 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10571 }
10572 else if(InvalidBG == 1)
10573 {
10574 for(int32_t dy=0; dy<16*mul; dy++)
10575 {
10576 for(int32_t dx=0; dx<16*mul; dx++)
10577 {
10578 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10579 }
10580 }
10581 }
10582 else
10583 {
10584 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10585 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10586 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10587 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10588 }
10589 }
10590
10591 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10592 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10593 }
10594
10595
10596 FONT *tf = font;
10597 font = tfont;
10598
10599 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10600 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10601
10602 if(buttons&2)
10603 {
10604 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10605 }
10606
10607 if(buttons&4)
10608 {
10609 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10610 }
10611
10612 font = tf;
10613
10614 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10615 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10616 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10617 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10618
10619 int32_t w = 640;
10620 int32_t h = 480;
10621 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10622 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10623 int32_t screen_xofs=window_xofs+6;
10624 int32_t screen_yofs=window_yofs+25;
10625
10626 custom_vsync();
10627 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10628 SCRFIX();
10629 //destroy_bitmap(buf);
10630 }
10631
10632 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10633 {
10634 int32_t page = tile&0xFF00;
10635 tile &= 0xFF;
10636
10637 if(!cols)
10638 tile += s;
10639 else
10640 {
10641 if(s==-COMBOS_PER_ROW)
10642 tile-=4;
10643
10644 if(s==COMBOS_PER_ROW)
10645 tile+=4;
10646
10647 if(s==-1)
10648 tile-=1;
10649
10650 if(s==1)
10651 tile+=1;
10652 }
10653
10654 /*
10655 if(s==1)
10656 {
10657 if((tile&3)==3)
10658 tile+=48;
10659 else
10660 ++tile;
10661 }
10662 if(s==-1)
10663 {
10664 if((tile&3)==0)
10665 tile-=48;
10666 else
10667 --tile;
10668 }
10669 }
10670 */
10671 bound(tile,0,255);
10672 tile += page;
10673
10674 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10675 tile2 = tile;
10676 }
10677
10678 void draw_combo_list_window()
10679 {
10680 int32_t window_xofs=0;
10681 int32_t window_yofs=0;
10682 int32_t w = 640;
10683 int32_t h = 480;
10684
10685 window_xofs=(zq_screen_w-w-12)>>1;
10686 window_yofs=(zq_screen_h-h-25-6)>>1;
10687 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10688 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10689 FONT *oldfont = font;
10690 font = get_zc_font(font_lfont);
10691 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10692 font=oldfont;
10693 }
10694
10695
10696 static int32_t _selected_combo=-1, _selected_cset=-1;
10697 bool select_combo_2(int32_t &cmb,int32_t &cs)
10698 {
10699 popup_zqdialog_start();
10700 reset_combo_animations();
10701 reset_combo_animations2();
10702 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10703 // static int32_t cmb=0;
10704 int32_t page=cmb>>8;
10705 int32_t tile2=cmb;
10706 int32_t done=0;
10707 int32_t tile_clicked=-1;
10708 int32_t t2;
10709 int32_t copy=-1;
10710 int32_t copycnt=0;
10711
10712 position_mouse_z(0);
10713
10714 go();
10715 int32_t w = 640;
10716 int32_t h = 480;
10717 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10718 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10719 int32_t screen_xofs=window_xofs+6;
10720 int32_t screen_yofs=window_yofs+25;
10721 int32_t panel_yofs=3;
10722 int32_t mul = 2;
10723 FONT *tfont = get_zc_font(font_lfont_l);
10724
10725 draw_combo_list_window();
10726 draw_combos(page,cs,combo_cols);
10727 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10728
10729 while(gui_mouse_b())
10730 {
10731 /* do nothing */
10732 rest(1);
10733 }
10734
10735 bool bdown=false;
10736 int32_t f=0;
10737 int otl = cmb, otl2 = tile2;
10738
10739 do
10740 {
10741 HANDLE_CLOSE_ZQDLG();
10742 if(exiting_program) break;
10743 rest(4);
10744 bool redraw=false;
10745
10746 if(mouse_z<0)
10747 {
10748 if(page<COMBO_PAGES-1)
10749 {
10750 ++page;
10751 cmb=tile2=(page<<8)+(cmb&0xFF);
10752 }
10753
10754 position_mouse_z(0);
10755 redraw=true;
10756 }
10757 else if(mouse_z>0)
10758 {
10759 if(page>0)
10760 {
10761 --page;
10762 cmb=tile2=(page<<8)+(cmb&0xFF);
10763 }
10764
10765 position_mouse_z(0);
10766 redraw=true;
10767 }
10768
10769 if(keypressed())
10770 {
10771 switch(readkey()>>8)
10772 {
10773 case KEY_DEL:
10774 cmb=0;
10775 done=2;
10776 break;
10777
10778 case KEY_ENTER_PAD:
10779 case KEY_ENTER:
10780 done=2;
10781 break;
10782
10783 case KEY_ESC:
10784 done=1;
10785 break;
10786
10787 case KEY_F1:
10788 onHelp();
10789 break;
10790
10791 case KEY_SPACE:
10792 combo_cols=!combo_cols;
10793 redraw=true;
10794 break;
10795
10796 case KEY_EQUALS:
10797 case KEY_PLUS_PAD:
10798 cs = (cs<13) ? cs+1:0;
10799 redraw=true;
10800 break;
10801
10802 case KEY_MINUS:
10803 case KEY_MINUS_PAD:
10804 cs = (cs>0) ? cs-1:13;
10805 redraw=true;
10806 break;
10807
10808 case KEY_UP:
10809 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10810 redraw=true;
10811 break;
10812
10813 case KEY_DOWN:
10814 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10815 redraw=true;
10816 break;
10817
10818 case KEY_LEFT:
10819 sel_combo(cmb,tile2,-1,combo_cols);
10820 redraw=true;
10821 break;
10822
10823 case KEY_RIGHT:
10824 sel_combo(cmb,tile2,1,combo_cols);
10825 redraw=true;
10826 break;
10827
10828 case KEY_PGUP:
10829 if(page>0)
10830 {
10831 --page;
10832 cmb=tile2=(page<<8)+(cmb&0xFF);
10833 }
10834
10835 redraw=true;
10836 break;
10837
10838 case KEY_PGDN:
10839 if(page<COMBO_PAGES-1)
10840 {
10841 ++page;
10842 cmb=tile2=(page<<8)+(cmb&0xFF);
10843 }
10844
10845 redraw=true;
10846 break;
10847
10848 case KEY_P:
10849 {
10850 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10851
10852 if(!cancelgetnum)
10853 page=(zc_min(choosepage,COMBO_PAGES-1));
10854
10855 cmb=tile2=(page<<8)+(cmb&0xFF);
10856 redraw=true;
10857 break;
10858 }
10859 }
10860
10861 clear_keybuf();
10862 }
10863
10864 if(gui_mouse_b()&1)
10865 {
10866 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10867 {
10868 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10869 {
10870 done=1;
10871 }
10872 }
10873
10874 int32_t x=gui_mouse_x()-screen_xofs;
10875 int32_t y=gui_mouse_y()-screen_yofs;
10876
10877 if(y>=0 && y<208*mul)
10878 {
10879 x=zc_min(zc_max(x,0),(320*mul)-1);
10880 int32_t t;
10881
10882 if(!combo_cols)
10883 {
10884 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10885 }
10886 else
10887 {
10888 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10889 }
10890
10891 bound(t,0,255);
10892 t+=page<<8;
10893 cmb=tile2=t;
10894
10895 if(tile_clicked!=t)
10896 {
10897 dclick_status=DCLICK_NOT;
10898 }
10899 else if(dclick_status == DCLICK_AGAIN)
10900 {
10901 while(gui_mouse_b())
10902 {
10903 /* do nothing */
10904 }
10905
10906 if(!combo_cols)
10907 {
10908 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10909 }
10910 else
10911 {
10912 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10913 }
10914
10915 if(t2!=t)
10916 {
10917 dclick_status=DCLICK_NOT;
10918 }
10919 else
10920 {
10921 done=2;
10922 }
10923 }
10924
10925 tile_clicked=t;
10926 }
10927 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10928 {
10929 if(y<(224*mul)+panel_yofs && page>0)
10930 {
10931 --page;
10932 redraw=true;
10933 }
10934
10935 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10936 {
10937 ++page;
10938 redraw=true;
10939 }
10940
10941 bdown=true;
10942 }
10943
10944 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10945 {
10946 FONT *tf = font;
10947 font = tfont;
10948
10949 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10950 {
10951 done=2;
10952 }
10953
10954 font = tf;
10955 }
10956 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10957 {
10958 FONT *tf = font;
10959 font = tfont;
10960
10961 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10962 combopage_animate = combopage_animate ? 0 : 1;
10963 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10964 redraw = true;
10965
10966 font = tf;
10967 }
10968
10969 bdown=true;
10970 }
10971
10972 bool r_click = false;
10973
10974 if(gui_mouse_b()&2 && !bdown)
10975 {
10976 int32_t x=gui_mouse_x()+screen_xofs;
10977 int32_t y=gui_mouse_y()+screen_yofs;
10978
10979 if(y>=0 && y<208*mul)
10980 {
10981 x=zc_min(zc_max(x,0),(320*mul)-1);
10982 int32_t t;
10983
10984 if(!combo_cols)
10985 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10986 else
10987 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10988
10989 bound(t,0,255);
10990 t+=page<<8;
10991
10992 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10993 cmb=tile2=t;
10994 }
10995
10996 bdown = r_click = true;
10997 f=8;
10998 }
10999
11000 if(gui_mouse_b()==0)
11001 bdown=false;
11002
11003 if((f%8) || InvalidBG == 1)
11004 redraw = true;
11005 if(otl != cmb || otl2 != tile2)
11006 {
11007 otl = cmb;
11008 otl2 = tile2;
11009 redraw = true;
11010 }
11011
11012 if(redraw || combopage_animate)
11013 draw_combos(page,cs,combo_cols);
11014
11015 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11016
11017 if(f&8)
11018 {
11019 int32_t x,y;
11020
11021 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11022 {
11023 if((i>>8)==page)
11024 {
11025 int32_t t=i&255;
11026
11027 if(!combo_cols)
11028 {
11029 x=(t%COMBOS_PER_ROW)<<5;
11030 y=(t/COMBOS_PER_ROW)<<5;
11031 }
11032 else
11033 {
11034 x=((t&3) + ((t/52)<<2)) << 5;
11035 y=((t%52)>>2) << 5;
11036 }
11037
11038 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11039 }
11040 }
11041
11042 SCRFIX();
11043 }
11044
11045 ++f;
11046
11047 }
11048 while(!done);
11049
11050 while(gui_mouse_b())
11051 {
11052 /* do nothing */
11053 rest(1);
11054 }
11055
11056 comeback();
11057 setup_combo_animations();
11058 setup_combo_animations2();
11059
11060 bool ret = done==2;
11061 if(ret)
11062 {
11063 _selected_combo = cmb;
11064 _selected_cset = cs;
11065 }
11066
11067 popup_zqdialog_end();
11068 return ret;
11069 }
11070
11071 bool select_combo_3(int32_t &cmb,int32_t &cs)
11072 {
11073 if(_selected_combo < 0)
11074 {
11075 _selected_combo = Combo;
11076 _selected_cset = CSet;
11077 }
11078 cmb = _selected_combo;
11079 cs = _selected_cset;
11080 return select_combo_2(cmb,cs);
11081 }
11082
11083 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11084 {
11085 static bitstring pasteflags;
11086 static const vector<CheckListInfo> advp_names =
11087 {
11088 { "Tile" },
11089 { "CSet2" },
11090 { "Solidity" },
11091 { "Animation" },
11092 { "Type" },
11093 { "Inherent Flag" },
11094 { "Attribytes" },
11095 { "Attrishorts" },
11096 { "Attributes" },
11097 { "Flags", "The 16 Flags on the 'Flags' tab" },
11098 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11099 { "Label" },
11100 { "Script" },
11101 { "Effect" },
11102 { "Triggers Tab" },
11103 { "Lifting Tab" },
11104 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11105 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11106 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11107 };
11108 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11109 return false;
11110
11111 //Paste to each combo in the range
11112 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11113 {
11114 combobuf[i].advpaste(combobuf[copy], pasteflags);
11115 }
11116
11117 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11118 {
11119 setup_combo_animations();
11120 setup_combo_animations2();
11121 }
11122
11123 return true;
11124 }
11125
11126 int32_t combo_screen(int32_t pg, int32_t tl)
11127 {
11128 popup_zqdialog_start();
11129 reset_combo_animations();
11130 reset_combo_animations2();
11131 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11132 static int32_t tile=0;
11133 static int32_t page=0;
11134
11135 if(pg>-1)
11136 page = pg;
11137
11138 if(tl>-1)
11139 tile = tl;
11140
11141 int32_t tile2=tile;
11142 int32_t done=0;
11143 int32_t cs = CSet;
11144 int32_t copy=-1;
11145 int32_t copycnt=0;
11146
11147 int32_t tile_clicked=-1;
11148 int32_t t2;
11149
11150 bool masscopy;
11151
11152 go();
11153 int32_t w = 640;
11154 int32_t h = 480;
11155 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11156 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11157 int32_t screen_xofs=window_xofs+6;
11158 int32_t screen_yofs=window_yofs+25;
11159 int32_t panel_yofs=3;
11160 int32_t mul = 2;
11161 FONT *tfont = get_zc_font(font_lfont_l);
11162
11163 draw_combo_list_window();
11164 draw_combos(page,cs,combo_cols);
11165 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11166 go_combos();
11167 position_mouse_z(0);
11168
11169 while(gui_mouse_b())
11170 {
11171 /* do nothing */
11172 }
11173
11174 bool bdown=false;
11175 int32_t f=0;
11176 int otl = tile, otl2 = tile2;
11177
11178 do
11179 {
11180 HANDLE_CLOSE_ZQDLG();
11181 if(exiting_program) break;
11182 rest(4);
11183 bool redraw=false;
11184
11185 if(mouse_z<0)
11186 {
11187 if(page<COMBO_PAGES-1)
11188 {
11189 ++page;
11190 tile=tile2=(page<<8)+(tile&0xFF);
11191 }
11192
11193 position_mouse_z(0);
11194 redraw=true;
11195 }
11196 else if(mouse_z>0)
11197 {
11198 if(page>0)
11199 {
11200 --page;
11201 tile=tile2=(page<<8)+(tile&0xFF);
11202 }
11203
11204 position_mouse_z(0);
11205 redraw=true;
11206 }
11207
11208 if(keypressed())
11209 {
11210 switch(readkey()>>8)
11211 {
11212 case KEY_ENTER_PAD:
11213 case KEY_ENTER:
11214 done=2;
11215 break;
11216
11217 case KEY_ESC:
11218 done=1;
11219 break;
11220
11221 case KEY_F1:
11222 onHelp();
11223 break;
11224
11225 case KEY_SPACE:
11226 combo_cols=!combo_cols;
11227 redraw=true;
11228 break;
11229
11230 case KEY_EQUALS:
11231 case KEY_PLUS_PAD:
11232 if(CHECK_CTRL_CMD)
11233 {
11234 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11235 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11236 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11237
11238 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11239 {
11240 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11241 0, NEWMAXTILES-1));
11242 }
11243
11244 setup_combo_animations();
11245 redraw=true;
11246 }
11247 else
11248 {
11249 cs = (cs<13) ? cs+1:0;
11250 redraw=true;
11251 }
11252
11253 break;
11254
11255 case KEY_MINUS:
11256 case KEY_MINUS_PAD:
11257 if(CHECK_CTRL_CMD)
11258 {
11259 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11260 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11261 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11262
11263 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11264 {
11265 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11266 0, NEWMAXTILES-1));
11267 }
11268
11269 setup_combo_animations();
11270 redraw=true;
11271 }
11272 else
11273 {
11274 cs = (cs>0) ? cs-1:13;
11275 redraw=true;
11276 }
11277
11278 break;
11279
11280 case KEY_UP:
11281 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11282 redraw=true;
11283 break;
11284
11285 case KEY_DOWN:
11286 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11287 redraw=true;
11288 break;
11289
11290 case KEY_LEFT:
11291 sel_combo(tile,tile2,-1,combo_cols);
11292 redraw=true;
11293 break;
11294
11295 case KEY_RIGHT:
11296 sel_combo(tile,tile2,1,combo_cols);
11297 redraw=true;
11298 break;
11299
11300 case KEY_PGUP:
11301 if(page>0)
11302 {
11303 --page;
11304 tile=tile2=(page<<8)+(tile&0xFF);
11305 }
11306
11307 redraw=true;
11308 break;
11309
11310 case KEY_PGDN:
11311 if(page<COMBO_PAGES-1)
11312 {
11313 ++page;
11314 tile=tile2=(page<<8)+(tile&0xFF);
11315 }
11316
11317 redraw=true;
11318 break;
11319
11320 case KEY_A:
11321 {
11322 tile=(page<<8);
11323 tile2=(page<<8)+(0xFF);
11324 }
11325
11326 redraw=true;
11327 break;
11328
11329 case KEY_P:
11330 {
11331 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11332
11333 if(!cancelgetnum)
11334 page=(zc_min(choosepage,COMBO_PAGES-1));
11335
11336 tile=tile2=(page<<8)+(tile&0xFF);
11337 redraw=true;
11338 }
11339 break;
11340
11341 case KEY_U:
11342 comeback_combos();
11343 redraw=true;
11344 break;
11345
11346 case KEY_E:
11347 go_combos();
11348 edit_combo(tile,false,cs);
11349 redraw=true;
11350 setup_combo_animations();
11351 setup_combo_animations2();
11352 break;
11353
11354 case KEY_C:
11355 go_combos();
11356 copy=zc_min(tile,tile2);
11357 copycnt=abs(tile-tile2)+1;
11358 redraw=true;
11359 break;
11360
11361 case KEY_H:
11362 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11363 {
11364 combobuf[i].flip^=1;
11365 byte w2=combobuf[i].walk;
11366 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11367 w2=combobuf[i].csets;
11368 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11369 }
11370
11371 redraw=true;
11372 saved=false;
11373 break;
11374
11375 case KEY_M:
11376 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11377 {
11378 move_combos(tile,tile2,copy,copycnt);
11379 saved=false;
11380 }
11381
11382 redraw=true;
11383 break;
11384
11385 case KEY_S:
11386 tile=tile2=zc_min(tile,tile2);
11387
11388 if(copy>=0 && tile!=copy)
11389 {
11390 go_combos();
11391
11392 for(int32_t i=0; i<copycnt; i++)
11393 {
11394 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11395 }
11396
11397 saved=false;
11398 setup_combo_animations();
11399 setup_combo_animations2();
11400 }
11401
11402 redraw=true;
11403 copy=-1;
11404 break;
11405
11406 case KEY_V:
11407 if((CHECK_CTRL_CMD) && copy != -1)
11408 {
11409 if(advpaste(tile, tile2, copy))
11410 {
11411 saved=false;
11412 redraw=true;
11413 copy=-1;
11414 }
11415
11416 break;
11417 }
11418
11419 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11420
11421 if(copy==-1)
11422 {
11423 go_combos();
11424
11425 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11426 {
11427 combobuf[i].flip^=2;
11428 byte w2=combobuf[i].walk;
11429 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11430 w2=combobuf[i].csets;
11431 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11432 }
11433
11434 saved=false;
11435 }
11436 else
11437 {
11438 go_combos();
11439 copy_combos(tile,tile2,copy,copycnt,masscopy);
11440 setup_combo_animations();
11441 setup_combo_animations2();
11442 saved=false;
11443 }
11444
11445 redraw=true;
11446 break;
11447 case KEY_R:
11448 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11449 {
11450 combobuf[i].flip = rotate_value(combobuf[i].flip);
11451 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11452 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11453 }
11454
11455 redraw=true;
11456 saved=false;
11457 break;
11458
11459 case KEY_I:
11460 {
11461 // rev.1509; Can now insert/remove all selected combos
11462 int32_t z=tile;
11463 int32_t numSelected = abs(tile-tile2) + 1;
11464 tile=zc_min(tile,tile2);
11465 tile2=MAXCOMBOS;
11466 copy = tile + numSelected; // copy=tile+1;
11467 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11468
11469 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11470 {
11471 char buf[64];
11472
11473 if(numSelected>1)
11474 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11475 else
11476 sprintf(buf,"Remove combo %d?",tile);
11477
11478 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11479 {
11480 move_combos(tile,tile2,copy, copycnt);
11481 //don't allow the user to undo; quest combo references are incorrect -DD
11482 go_combos();
11483 redraw=true;
11484 saved=false;
11485 }
11486 }
11487 else
11488 {
11489 char buf[64];
11490
11491 if(numSelected>1)
11492 sprintf(buf,"Insert %d blank combos?",numSelected);
11493 else
11494 sprintf(buf,"Insert a blank combo?");
11495
11496 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11497 {
11498 move_combos(copy,tile2,tile, copycnt);
11499 go_combos();
11500 redraw=true;
11501 saved=false;
11502 }
11503 }
11504
11505 copy=-1;
11506 tile2=tile=z;
11507 }
11508 break;
11509
11510 case KEY_DEL:
11511 {
11512 char buf[40];
11513
11514 if(tile==tile2)
11515 {
11516 sprintf(buf,"Delete combo %d?",tile);
11517 }
11518 else
11519 {
11520 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11521 }
11522
11523 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11524 {
11525 go_combos();
11526
11527 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11528 {
11529 clear_combo(i);
11530 }
11531
11532 tile=tile2=zc_min(tile,tile2);
11533 redraw=true;
11534 saved=false;
11535 setup_combo_animations();
11536 setup_combo_animations2();
11537 }
11538 }
11539 break;
11540 }
11541
11542 clear_keybuf();
11543 }
11544
11545 if(gui_mouse_b()&1)
11546 {
11547 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11548 {
11549 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11550 {
11551 done=1;
11552 }
11553 }
11554
11555 int32_t x=gui_mouse_x()-screen_xofs;
11556 int32_t y=gui_mouse_y()-screen_yofs;
11557
11558 if(y>=0 && y<(208*mul))
11559 {
11560 x=zc_min(zc_max(x,0),(320*mul)-1);
11561 int32_t t;
11562
11563 if(!combo_cols)
11564 {
11565 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11566 }
11567 else
11568 {
11569 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11570 }
11571
11572 bound(t,0,255);
11573 t+=page<<8;
11574
11575 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11576 {
11577 tile2=t;
11578 }
11579 else
11580 {
11581 tile=tile2=t;
11582 }
11583
11584 if(tile_clicked!=t)
11585 {
11586 dclick_status=DCLICK_NOT;
11587 }
11588 else if(dclick_status == DCLICK_AGAIN)
11589 {
11590 while(gui_mouse_b())
11591 {
11592 /* do nothing */
11593 rest(1);
11594 }
11595
11596 if(!combo_cols)
11597 {
11598 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11599 }
11600 else
11601 {
11602 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11603 }
11604
11605 bound(t2,0,255);
11606 t2+=page<<8;
11607
11608 if(t2!=t)
11609 {
11610 dclick_status=DCLICK_NOT;
11611 }
11612 else
11613 {
11614 go_combos();
11615 edit_combo(tile,false,cs);
11616 redraw=true;
11617 setup_combo_animations();
11618 setup_combo_animations2();
11619 }
11620 }
11621
11622 tile_clicked=t;
11623 }
11624 else if(x>(300*mul) && !bdown)
11625 {
11626 if(y<(224*mul)+panel_yofs && page>0)
11627 {
11628 --page;
11629 redraw=true;
11630 }
11631
11632 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11633 {
11634 ++page;
11635 redraw=true;
11636 }
11637
11638 bdown=true;
11639 }
11640
11641 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11642 {
11643 FONT *tf = font;
11644 font = tfont;
11645
11646 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11647 {
11648 font = tf;
11649 edit_combo(tile,false,cs);
11650 redraw=true;
11651 }
11652
11653 font = tf;
11654 }
11655 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11656 {
11657 FONT *tf = font;
11658 font = tfont;
11659
11660 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11661 {
11662 done=1;
11663 }
11664
11665 font = tf;
11666 }
11667 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11668 {
11669 FONT *tf = font;
11670 font = tfont;
11671
11672 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11673 combopage_animate = combopage_animate ? 0 : 1;
11674 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11675 redraw = true;
11676
11677 font = tf;
11678 }
11679
11680 bdown=true;
11681 }
11682
11683 bool r_click = false;
11684
11685 if(gui_mouse_b()&2 && !bdown)
11686 {
11687 int32_t x=gui_mouse_x()-screen_xofs;
11688 int32_t y=gui_mouse_y()-screen_yofs;
11689
11690 if(y>=0 && y<(208*mul))
11691 {
11692 x=zc_min(zc_max(x,0),(320*mul)-1);
11693 int32_t t;
11694
11695 if(!combo_cols)
11696 {
11697 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11698 }
11699 else
11700 {
11701 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11702 }
11703
11704 bound(t,0,255);
11705 t+=page<<8;
11706
11707 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11708 {
11709 tile=tile2=t;
11710 }
11711 }
11712
11713 bdown = r_click = true;
11714 f=8;
11715 }
11716
11717 REDRAW:
11718
11719 if(gui_mouse_b()==0)
11720 bdown=false;
11721
11722 if((f%8) || InvalidBG == 1)
11723 redraw = true;
11724 if(otl != tile || otl2 != tile2)
11725 {
11726 otl = tile;
11727 otl2 = tile2;
11728 redraw = true;
11729 }
11730
11731 if(redraw || combopage_animate)
11732 draw_combos(page,cs,combo_cols);
11733
11734 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11735
11736 if(f&8)
11737 {
11738 int32_t x,y;
11739
11740 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11741 {
11742 if((i>>8)==page)
11743 {
11744 int32_t t=i&255;
11745
11746 if(!combo_cols)
11747 {
11748 x=(t%COMBOS_PER_ROW)<<5;
11749 y=(t/COMBOS_PER_ROW)<<5;
11750 }
11751 else
11752 {
11753 x=((t&3) + ((t/52)<<2)) << 5;
11754 y=((t%52)>>2) << 5;
11755 }
11756
11757 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11758 }
11759 }
11760
11761 SCRFIX();
11762 }
11763
11764 ++f;
11765
11766 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11767 if(r_click)
11768 {
11769 NewMenu rcmenu
11770 {
11771 { "Copy", [&]()
11772 {
11773 go_combos();
11774 copy=zc_min(tile,tile2);
11775 copycnt=abs(tile-tile2)+1;
11776 } },
11777 { "Paste", [&]()
11778 {
11779 if((CHECK_CTRL_CMD) && copy != -1)
11780 {
11781 if(advpaste(tile, tile2, copy))
11782 {
11783 saved=false;
11784 redraw=true;
11785 copy=-1;
11786 }
11787 return;
11788 }
11789
11790 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11791
11792 if(copy>-1)
11793 {
11794 go_combos();
11795 copy_combos(tile,tile2,copy,copycnt,masscopy);
11796 setup_combo_animations();
11797 setup_combo_animations2();
11798 saved=false;
11799 }
11800 } },
11801 { "Adv. Paste", [&]()
11802 {
11803 if(copy > -1)
11804 {
11805 if(advpaste(tile, tile2, copy))
11806 {
11807 saved=false;
11808 redraw=true;
11809 copy=-1;
11810 }
11811 }
11812 } },
11813 { "Swap", [&]()
11814 {
11815 tile=tile2=zc_min(tile,tile2);
11816
11817 if(copy>=0 && tile!=copy)
11818 {
11819 go_combos();
11820
11821 for(int32_t i=0; i<copycnt; i++)
11822 {
11823 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11824 }
11825
11826 saved=false;
11827 setup_combo_animations();
11828 setup_combo_animations2();
11829 }
11830 copy=-1;
11831 } },
11832 { "Delete", [&]()
11833 {
11834 string msg;
11835
11836 if(tile==tile2)
11837 msg = fmt::format("Delete combo {}?",tile);
11838 else
11839 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11840 bool didconfirm = false;
11841 AlertDialog("Confirm Delete",msg,
11842 [&](bool ret,bool)
11843 {
11844 if(ret)
11845 didconfirm = true;
11846 }).show();
11847 if(didconfirm)
11848 {
11849 go_combos();
11850
11851 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11852 clear_combo(i);
11853
11854 tile=tile2=zc_min(tile,tile2);
11855 saved=false;
11856 }
11857 } },
11858 {},
11859 { "Edit", [&]()
11860 {
11861 go_combos();
11862 edit_combo(tile,false,cs);
11863 } },
11864 { "Insert", [&]()
11865 {
11866 int z = tile;
11867 int count = abs(tile-tile2)+1;
11868 tile = zc_min(tile,tile2);
11869 tile2 = MAXCOMBOS;
11870 copy = tile+count;
11871 copycnt = MAXCOMBOS-tile-count;
11872
11873 string msg;
11874
11875 if(count>1)
11876 msg = fmt::format("Insert combos {} - {}?"
11877 " This will offset all of the combos that follow!",tile, copy-1);
11878 else
11879 msg = fmt::format("Insert combo {}?"
11880 " This will offset all of the combos that follow!",tile);
11881
11882 bool didconfirm = false;
11883 AlertDialog("Confirm Insert",msg,
11884 [&](bool ret,bool)
11885 {
11886 if(ret)
11887 didconfirm = true;
11888 }).show();
11889 if(didconfirm)
11890 move_combos(copy, tile2, tile, copycnt);
11891 else return;
11892
11893 copy = -1;
11894 tile2 = tile = z;
11895
11896 //don't allow the user to undo; quest combo references are incorrect -DD
11897 go_combos();
11898 saved = false;
11899 } },
11900 { "Remove", [&]()
11901 {
11902 int z = tile;
11903 int count = abs(tile-tile2)+1;
11904 tile = zc_min(tile,tile2);
11905 tile2 = MAXCOMBOS;
11906 copy = tile+count;
11907 copycnt = MAXCOMBOS-tile-count;
11908
11909 string msg;
11910
11911 if(count>1)
11912 msg = fmt::format("Remove combos {} - {}?"
11913 " This will offset all of the combos that follow!",tile, copy-1);
11914 else
11915 msg = fmt::format("Remove combo {}?"
11916 " This will offset all of the combos that follow!",tile);
11917
11918 bool didconfirm = false;
11919 AlertDialog("Confirm Remove",msg,
11920 [&](bool ret,bool)
11921 {
11922 if(ret)
11923 didconfirm = true;
11924 }).show();
11925 if(didconfirm)
11926 move_combos(tile, tile2, copy, copycnt);
11927 else return;
11928
11929 copy = -1;
11930 tile2 = tile = z;
11931
11932 //don't allow the user to undo; quest combo references are incorrect -DD
11933 go_combos();
11934 saved = false;
11935 } },
11936 {},
11937 { "Locations", [&]()
11938 {
11939 int32_t z = Combo;
11940 Combo = tile;
11941 onComboLocationReport();
11942 Combo = z;
11943 } },
11944 };
11945 rcmenu.pop(window_mouse_x(),window_mouse_y());
11946 redraw = true;
11947 r_click = false;
11948 goto REDRAW;
11949 }
11950
11951 }
11952 while(!done);
11953
11954 while(gui_mouse_b())
11955 rest(1);
11956 comeback();
11957 setup_combo_animations();
11958 setup_combo_animations2();
11959 _selected_combo = tile;
11960 _selected_cset = cs;
11961 popup_zqdialog_end();
11962 return done-1;
11963 }
11964
11965 int32_t onCombos()
11966 {
11967 // reset_combo_animations();
11968 combo_screen(-1,-1);
11969 // setup_combo_animations();
11970 refresh(rALL);
11971 return D_O_K;
11972 }
11973
11974 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11975 {
11976 //these are here to bypass compiler warnings about unused arguments
11977 d=d;
11978 c=c;
11979
11980 if(msg==MSG_CLICK)
11981 {
11982 int32_t t=curr_combo.o_tile;
11983 int32_t f=curr_combo.flip;
11984
11985 if(select_tile(t,f,1,CSet,true,0,true))
11986 {
11987 curr_combo.tile=t;
11988 curr_combo.o_tile=t;
11989 curr_combo.flip=f;
11990 return D_REDRAW;
11991 }
11992 }
11993
11994 return D_O_K;
11995 }
11996
11997 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11998 {
11999 //these are here to bypass compiler warnings about unused arguments
12000 c=c;
12001
12002 if(msg==MSG_DRAW)
12003 {
12004 FONT *f = get_zc_font(font_lfont_l);
12005 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12006 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12007 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12008 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12009 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12010 }
12011
12012 return D_O_K;
12013 }
12014
12015 int32_t click_d_ctile_proc()
12016 {
12017 d_ctile_proc(MSG_CLICK,NULL,0);
12018 return D_REDRAW;
12019 }
12020
12021 int32_t click_d_combo_proc();
12022
12023 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12024 {
12025 if(index<0)
12026 {
12027 *list_size = bidcomboscripts_cnt;
12028 return NULL;
12029 }
12030
12031 return bidcomboscripts[index].first.c_str();
12032 }
12033 9 ListData comboscript_list(comboscriptdroplist, &font);
12034
12035 bool call_combo_editor(int32_t);
12036 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12037 {
12038 FONT* ofont = font;
12039 //CSet = cs;
12040 reset_combo_animations();
12041 reset_combo_animations2();
12042 bool edited = call_combo_editor(c);
12043 font = ofont;
12044
12045 if(freshen)
12046 {
12047 refresh(rALL);
12048 }
12049
12050 setup_combo_animations();
12051 setup_combo_animations2();
12052
12053 return edited;
12054 }
12055
12056 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12057 {
12058 switch(msg)
12059 {
12060 case MSG_CLICK:
12061 {
12062 int32_t cs = d->d2;
12063 int32_t f = 0;
12064
12065 if(select_tile(d->d1,f,1,cs,true))
12066 {
12067 int32_t ok=1;
12068
12069 if(newtilebuf[d->d1].format==tf8Bit)
12070 jwin_alert("Warning",
12071 "You have selected an 8-bit tile.",
12072 "It will not be drawn correctly",
12073 "on the file select screen.",
12074 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12075
12076 return D_REDRAW;
12077 }
12078 }
12079 break;
12080
12081 case MSG_DRAW:
12082 d->w = 32+4;
12083 d->h = 32+4;
12084
12085 BITMAP *buf = create_bitmap_ex(8,16,16);
12086 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12087
12088 if(buf && bigbmp)
12089 {
12090 clear_bitmap(buf);
12091 overtile16(buf,d->d1,0,0,d->fg,0);
12092 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12093 destroy_bitmap(buf);
12094 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12095 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12096 destroy_bitmap(bigbmp);
12097 }
12098
12099 break;
12100 }
12101
12102 return D_O_K;
12103 }
12104
12105 static DIALOG icon_dlg[] =
12106 {
12107 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12108 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12109 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12110 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12111 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12112 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12113 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12114 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12115 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12116 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12117 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12118 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12119 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12120 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12121 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12122 };
12123
12124 int32_t onIcons()
12125 {
12126 PALETTE pal;
12127 // pal = RAMpal;
12128 memcpy(pal,RAMpal,sizeof(RAMpal));
12129 icon_dlg[0].dp2=get_zc_font(font_lfont);
12130
12131 for(int32_t i=0; i<4; i++)
12132 {
12133 icon_dlg[i+2].d1 = QMisc.icons[i];
12134 icon_dlg[i+2].fg = i+6;
12135 load_cset(pal, i+6, pSprite(i+spICON1));
12136 }
12137
12138 zc_set_palette(pal);
12139
12140 large_dialog(icon_dlg);
12141
12142 int32_t ret = do_zqdialog(icon_dlg,7);
12143
12144 if(ret==6)
12145 {
12146 for(int32_t i=0; i<4; i++)
12147 {
12148 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12149 {
12150 QMisc.icons[i] = icon_dlg[i+2].d1;
12151 saved=false;
12152 }
12153 }
12154 }
12155
12156 zc_set_palette(RAMpal);
12157 return D_O_K;
12158 }
12159
12160 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12161 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12162 {
12163 if(msg == MSG_DRAW)
12164 {
12165 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12166 }
12167
12168 return D_O_K;
12169 }
12170
12171 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12172 {
12173 switch(msg)
12174 {
12175 case MSG_CLICK:
12176 {
12177 if((d->flags&D_NOCLICK))
12178 break;
12179
12180 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12181 int32_t combo2;
12182 int32_t cs;
12183
12184 if(CHECK_ALT) //place selected cmb/cs
12185 {
12186 if(gui_mouse_b()&1)
12187 {
12188 if(!CHECK_SHIFT)
12189 d->d1 = Combo;
12190 d->fg = CSet;
12191 }
12192
12193 return ret|D_REDRAW;
12194 }
12195 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12196 {
12197 d->d1=0;
12198 d->fg=0;
12199 return ret|D_REDRAW;
12200 }
12201 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12202 {
12203 combo2=d->d1;
12204 cs=d->fg;
12205
12206 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12207 {
12208 d->d1=combo2;
12209 d->fg=cs;
12210 }
12211
12212 return ret|D_REDRAW;
12213 }
12214 else return ret|D_REDRAWME;
12215 }
12216 break;
12217
12218 case MSG_DRAW:
12219 {
12220 d->w = 32;
12221 d->h = 32;
12222
12223 BITMAP *buf = create_bitmap_ex(8,16,16);
12224 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12225
12226 if(buf && bigbmp)
12227 {
12228 clear_bitmap(buf);
12229
12230 if(d->d1==-1) // Display curr_combo instead of combobuf
12231 {
12232 newcombo hold = combobuf[0];
12233 combobuf[0] = curr_combo;
12234 putcombo(buf,0,0,0,d->fg);
12235 combobuf[0] = hold;
12236 }
12237 else if(d->d1)
12238 {
12239 putcombo(buf,0,0,d->d1,d->fg);
12240 }
12241
12242 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12243 destroy_bitmap(buf);
12244 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12245 destroy_bitmap(bigbmp);
12246 }
12247 }
12248 break;
12249 }
12250 return D_O_K;
12251 }
12252
12253 // Hey, let's have a few hundred more lines of code, why not.
12254
12255 #define MR_4BIT 0
12256 #define MR_8BIT 1
12257
12258 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12259 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12260 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12261
12262 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12263 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12264
12265 static int32_t massRecolorDraggedColor=-1;
12266 static int32_t massRecolorCSet;
12267 static bool massRecolorIgnoreBlank=true;
12268 static byte massRecolorType=MR_4BIT;
12269
12270 // Shows the sets of colors to replace from/to.
12271 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12272 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12273 #define D_CSET D_USER
12274 #define D_SETTABLE (D_USER<<1)
12275 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12276 {
12277 BITMAP* bmp=screen;
12278 int32_t colorWidth=(d->w-4)/16;
12279 byte* colors=static_cast<byte*>(d->dp);
12280
12281 switch(msg)
12282 {
12283 case MSG_DRAW:
12284 {
12285 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12286
12287 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12288 for(int32_t c=0; c<16; c++)
12289 {
12290 rectfill(bmp,
12291 d->x+2+c*colorWidth, d->y+2,
12292 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12293 baseColor+colors[c]);
12294 }
12295 }
12296 break;
12297
12298 case MSG_LPRESS:
12299 {
12300 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12301
12302 if(x >= 0 && x < 16) //sanity check!
12303 {
12304 massRecolorDraggedColor=colors[x];
12305 }
12306 }
12307 break;
12308
12309 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12310 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12311 {
12312 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12313 if(x >= 0 && x < 16) //sanity check!
12314 {
12315 colors[x]=massRecolorDraggedColor;
12316 d->flags|=D_DIRTY;
12317 }
12318 }
12319 massRecolorDraggedColor=-1;
12320 break;
12321 }
12322
12323 return D_O_K;
12324 }
12325
12326 // Used for the full palette in 8-bit mode.
12327 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12328 {
12329 BITMAP* bmp=screen;
12330 int colorWidth=(d->w-4)/16;
12331 d->h = 4+(colorWidth*14);
12332 int colorHeight=colorWidth;
12333
12334 switch(msg)
12335 {
12336 case MSG_DRAW:
12337 {
12338 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12339 for(int cset=0; cset<=13; cset++)
12340 {
12341 for(int color=0; color<16; color++)
12342 {
12343 rectfill(bmp,
12344 d->x+2+color*colorWidth,
12345 d->y+2+cset*colorHeight,
12346 d->x+2+((color+1)*colorWidth)-1,
12347 d->y+2+((cset+1)*colorHeight)-1,
12348 cset*16+color);
12349 }
12350 }
12351 }
12352 break;
12353
12354 case MSG_LPRESS:
12355 {
12356 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12357 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12358 massRecolorDraggedColor=cset*16+color;
12359 }
12360 break;
12361 }
12362
12363 return D_O_K;
12364 }
12365
12366 static DIALOG recolor_4bit_dlg[] =
12367 {
12368 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12369 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12370
12371 // 1
12372 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12373 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12374 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12375 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12376
12377 // 5
12378 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12379 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12380 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12381 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12382 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12383 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12384 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12385 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12386 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12387 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12388 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12389 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12390 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12391 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12392 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12393
12394 // 20
12395 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12396 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12397 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12398 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12399 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12400
12401 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12402 };
12403
12404 #define MR4_SRC_COLORS 2
12405 #define MR4_DEST_COLORS 4
12406 #define MR4_8BIT_EFFECT_START 6
12407 #define MR4_IGNORE_BLANK 20
12408 #define MR4_RESET 21
12409 #define MR4_SWITCH 22
12410 #define MR4_OK 23
12411 #define MR4_CANCEL 24
12412
12413 static DIALOG recolor_8bit_dlg[] =
12414 {
12415 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12416 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12417
12418 // 1
12419 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12420 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12421 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12422 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12423 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12424
12425 // 6
12426 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12427 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12428 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12429 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12430 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12431
12432 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12433 };
12434
12435 #define MR8_SRC_COLORS 2
12436 #define MR8_DEST_COLORS 4
12437 #define MR8_PALETTE 5
12438 #define MR8_IGNORE_BLANK 6
12439 #define MR8_RESET 7
12440 #define MR8_SWITCH 8
12441 #define MR8_OK 9
12442 #define MR8_CANCEL 10
12443
12444 static void massRecolorInit(int32_t cset)
12445 {
12446 massRecolorDraggedColor=-1;
12447 massRecolorCSet=cset;
12448
12449 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12450 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12451
12452 for(int32_t i=0; i<=13; i++)
12453 {
12454 if((massRecolor8BitCSets&(1<<i))!=0)
12455 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12456 else
12457 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12458 }
12459
12460 if(massRecolorIgnoreBlank)
12461 {
12462 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12463 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12464 }
12465 else
12466 {
12467 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12468 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12469 }
12470
12471 large_dialog(recolor_4bit_dlg);
12472 large_dialog(recolor_8bit_dlg);
12473
12474 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12475 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12476 {
12477 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12478 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12479 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12480 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12481
12482 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12483 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12484 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12485 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12486 recolor_8bit_dlg[MR8_PALETTE].x++;
12487 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12488 recolor_8bit_dlg[MR8_PALETTE].y++;
12489 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12490 }
12491 }
12492
12493 static void massRecolorApplyChanges()
12494 {
12495 massRecolor8BitCSets=0;
12496 for(int32_t i=0; i<=13; i++)
12497 {
12498 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12499 massRecolor8BitCSets|=1<<i;
12500 }
12501
12502 if(massRecolorType==MR_4BIT)
12503 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12504 else
12505 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12506 }
12507
12508 static bool massRecolorSetup(int32_t cset)
12509 {
12510 massRecolorInit(cset);
12511
12512 // Remember the current colors in case the user cancels.
12513 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12514 for(int32_t i=0; i<16; i++)
12515 {
12516 oldDest4Bit[i]=massRecolorDest4Bit[i];
12517 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12518 oldDest8Bit[i]=massRecolorDest8Bit[i];
12519 }
12520
12521 byte type=massRecolorType;
12522 int32_t ret;
12523 do
12524 {
12525 HANDLE_CLOSE_ZQDLG();
12526 if(exiting_program) break;
12527 if(type==MR_4BIT)
12528 {
12529 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12530 if(ret==MR4_SWITCH)
12531 type=MR_8BIT;
12532 }
12533 else
12534 {
12535 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12536 if(ret==MR8_SWITCH)
12537 type=MR_4BIT;
12538 }
12539 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12540
12541 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12542 {
12543 for(int32_t i=0; i<16; i++)
12544 {
12545 massRecolorDest4Bit[i]=oldDest4Bit[i];
12546 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12547 massRecolorDest8Bit[i]=oldDest8Bit[i];
12548 }
12549 return false;
12550 }
12551
12552 // OK
12553 massRecolorType=type;
12554 massRecolorApplyChanges();
12555 return true;
12556 }
12557
12558 static void massRecolorApply4Bit(int32_t tile)
12559 {
12560 byte buf[256];
12561 unpack_tile(newtilebuf, tile, 0, true);
12562
12563 if(newtilebuf[tile].format==tf4Bit)
12564 {
12565 for(int32_t i=0; i<256; i++)
12566 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12567 }
12568 else // 8-bit
12569 {
12570 for(int32_t i=0; i<256; i++)
12571 {
12572 word cset=unpackbuf[i]>>4;
12573 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12574 {
12575 word color=unpackbuf[i]&15;
12576 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12577 }
12578 else
12579 buf[i]=unpackbuf[i];
12580 }
12581 }
12582
12583 pack_tile(newtilebuf, buf, tile);
12584 }
12585
12586 static void massRecolorApply8Bit(int32_t tile)
12587 {
12588 byte buf[256];
12589 unpack_tile(newtilebuf, tile, 0, true);
12590
12591 for(int32_t i=0; i<256; i++)
12592 {
12593 byte color=unpackbuf[i];
12594 for(int32_t j=0; j<16; j++)
12595 {
12596 if(massRecolorSrc8Bit[j]==color)
12597 {
12598 color=massRecolorDest8Bit[j];
12599 break;
12600 }
12601 }
12602 buf[i]=color;
12603 }
12604
12605 pack_tile(newtilebuf, buf, tile);
12606 }
12607
12608 static void massRecolorApply(int32_t tile)
12609 {
12610 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12611 return;
12612
12613 if(massRecolorType==MR_4BIT)
12614 massRecolorApply4Bit(tile);
12615 else // 8-bit
12616 {
12617 if(newtilebuf[tile].format==tf4Bit)
12618 return;
12619 massRecolorApply8Bit(tile);
12620 }
12621 }
12622
12623 static void massRecolorReset4Bit()
12624 {
12625 for(int32_t i=0; i<16; i++)
12626 massRecolorDest4Bit[i]=i;
12627 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12628 }
12629
12630 static void massRecolorReset8Bit()
12631 {
12632 for(int32_t i=0; i<16; i++)
12633 {
12634 massRecolorSrc8Bit[i]=0;
12635 massRecolorDest8Bit[i]=0;
12636 }
12637
12638 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12639 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12640 }
12641
12642 6 void center_zq_tiles_dialogs()
12643 {
12644 6 jwin_center_dialog(create_relational_tiles_dlg);
12645 6 jwin_center_dialog(icon_dlg);
12646 6 jwin_center_dialog(leech_dlg);
12647 6 jwin_center_dialog(move_textbox_list_dlg);
12648 6 jwin_center_dialog(recolor_4bit_dlg);
12649 6 jwin_center_dialog(recolor_8bit_dlg);
12650 6 }
12651
12652 //.ZCOMBO
12653
12654 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12655 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12656
12657 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12658 dword section_version, dword section_cversion, int32_t index, int32_t count)
12659 {
12660 newcombo temp_combo;
12661 for ( int32_t tilect = 0; tilect < count; tilect++ )
12662 {
12663 temp_combo.clear();
12664 if(!p_igetw(&temp_combo.tile,f))
12665 {
12666 return 0;
12667 }
12668 temp_combo.o_tile = temp_combo.tile;
12669
12670 if(!p_getc(&temp_combo.flip,f))
12671 {
12672 return 0;
12673 }
12674
12675 if(!p_getc(&temp_combo.walk,f))
12676 {
12677 return 0;
12678 }
12679
12680 if(!p_getc(&temp_combo.type,f))
12681 {
12682 return 0;
12683 }
12684
12685 if(!p_getc(&temp_combo.csets,f))
12686 {
12687 return 0;
12688 }
12689
12690 if(!p_getc(&temp_combo.frames,f))
12691 {
12692 return 0;
12693 }
12694
12695 if(!p_getc(&temp_combo.speed,f))
12696 {
12697 return 0;
12698 }
12699
12700 if(!p_igetw(&temp_combo.nextcombo,f))
12701 {
12702 return 0;
12703 }
12704
12705 if(!p_getc(&temp_combo.nextcset,f))
12706 {
12707 return 0;
12708 }
12709
12710 if(!p_getc(&temp_combo.flag,f))
12711 {
12712 return 0;
12713 }
12714
12715 if(!p_getc(&temp_combo.skipanim,f))
12716 {
12717 return 0;
12718 }
12719
12720 if(!p_igetw(&temp_combo.nexttimer,f))
12721 {
12722 return 0;
12723 }
12724
12725 if(!p_getc(&temp_combo.skipanimy,f))
12726 {
12727 return 0;
12728 }
12729
12730 if(!p_getc(&temp_combo.animflags,f))
12731 {
12732 return 0;
12733 }
12734
12735 //2.55 starts here
12736 if ( zversion >= 0x255 )
12737 {
12738 if ( section_version >= 12 )
12739 {
12740 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12741 {
12742 if(!p_igetl(&temp_combo.attributes[q],f))
12743 {
12744 return 0;
12745 }
12746 }
12747 if(!p_igetl(&temp_combo.usrflags,f))
12748 {
12749 return 0;
12750 }
12751 for ( int32_t q = 0; q < 3; q++ )
12752 {
12753 if(!p_igetl(&temp_combo.triggerflags[q],f))
12754 {
12755 return 0;
12756 }
12757 }
12758
12759 if(!p_igetl(&temp_combo.triggerlevel,f))
12760 {
12761 return 0;
12762 }
12763 if(section_version >= 22)
12764 {
12765 if(!p_getc(&temp_combo.triggerbtn,f))
12766 {
12767 return 0;
12768 }
12769 }
12770 if(section_version < 23)
12771 {
12772 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12773 {
12774 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12775 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12776 case cTRIGGERGENERIC: case cCSWITCH:
12777 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12778 }
12779 }
12780 if(section_version >= 24)
12781 {
12782 if(!p_getc(&temp_combo.triggeritem,f))
12783 {
12784 return 0;
12785 }
12786 if(!p_getc(&temp_combo.trigtimer,f))
12787 {
12788 return 0;
12789 }
12790 }
12791 if(section_version >= 25)
12792 {
12793 if(!p_getc(&temp_combo.trigsfx,f))
12794 {
12795 return 0;
12796 }
12797 }
12798 else
12799 {
12800 switch(temp_combo.type)
12801 {
12802 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12803 if(!(temp_combo.usrflags & cflag3))
12804 temp_combo.attribytes[3] = WAV_DOOR;
12805 temp_combo.usrflags &= ~cflag3;
12806 break;
12807 }
12808 }
12809 if(section_version < 26)
12810 {
12811 if(temp_combo.type == cARMOS)
12812 {
12813 if(temp_combo.usrflags & cflag1)
12814 temp_combo.usrflags |= cflag3;
12815 }
12816 }
12817 if(section_version >= 27)
12818 {
12819 if(!p_igetl(&temp_combo.trigchange,f))
12820 {
12821 return qe_invalid;
12822 }
12823 }
12824 else
12825 {
12826 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12827 temp_combo.trigchange = 1;
12828 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12829 temp_combo.trigchange = -1;
12830 else temp_combo.trigchange = 0;
12831 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12832 }
12833 if(section_version >= 29)
12834 {
12835 if(!p_igetw(&temp_combo.trigprox,f))
12836 {
12837 return qe_invalid;
12838 }
12839 if(!p_getc(&temp_combo.trigctr,f))
12840 {
12841 return qe_invalid;
12842 }
12843 if(!p_igetl(&temp_combo.trigctramnt,f))
12844 {
12845 return qe_invalid;
12846 }
12847 }
12848 else
12849 {
12850 temp_combo.trigprox = 0;
12851 temp_combo.trigctr = 0;
12852 temp_combo.trigctramnt = 0;
12853 }
12854 if(section_version >= 30)
12855 {
12856 if(!p_getc(&temp_combo.triglbeam,f))
12857 {
12858 return qe_invalid;
12859 }
12860 }
12861 else temp_combo.triglbeam = 0;
12862 if(section_version >= 31)
12863 {
12864 if(!p_getc(&temp_combo.trigcschange,f))
12865 {
12866 return qe_invalid;
12867 }
12868 if(!p_igetw(&temp_combo.spawnitem,f))
12869 {
12870 return qe_invalid;
12871 }
12872 if(!p_igetw(&temp_combo.spawnenemy,f))
12873 {
12874 return qe_invalid;
12875 }
12876 if(!p_getc(&temp_combo.exstate,f))
12877 {
12878 return qe_invalid;
12879 }
12880 if(!p_igetl(&temp_combo.spawnip,f))
12881 {
12882 return qe_invalid;
12883 }
12884 if(!p_getc(&temp_combo.trigcopycat,f))
12885 {
12886 return qe_invalid;
12887 }
12888 }
12889 else
12890 {
12891 temp_combo.trigcschange = 0;
12892 temp_combo.spawnitem = 0;
12893 temp_combo.spawnenemy = 0;
12894 temp_combo.exstate = -1;
12895 temp_combo.spawnip = 0;
12896 temp_combo.trigcopycat = 0;
12897 }
12898 if(section_version >= 32)
12899 {
12900 if(!p_getc(&temp_combo.trigcooldown,f))
12901 {
12902 return qe_invalid;
12903 }
12904 }
12905 else
12906 {
12907 temp_combo.trigcooldown = 0;
12908 }
12909 char label[12];
12910 label[11] = '\0';
12911 for ( int32_t q = 0; q < 11; q++ )
12912 {
12913 if(!p_getc(&label[q],f))
12914 {
12915 return 0;
12916 }
12917 }
12918 temp_combo.label = label;
12919 }
12920 if ( section_version >= 13 )
12921 {
12922 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12923 {
12924 if(!p_getc(&temp_combo.attribytes[q],f))
12925 {
12926 return 0;
12927 }
12928 }
12929
12930 }
12931 }
12932
12933 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12934 {
12935 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12936 {
12937 combobuf[index+(tilect)] = temp_combo;
12938 }
12939 }
12940 }
12941
12942 return 1;
12943 }
12944
12945 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12946 {
12947 dword section_version=0;
12948 dword section_cversion=0;
12949 int32_t zversion = 0;
12950 int32_t zbuild = 0;
12951
12952 if(!p_igetl(&zversion,f))
12953 {
12954 return 0;
12955 }
12956 if(!p_igetl(&zbuild,f))
12957 {
12958 return 0;
12959 }
12960 if(!p_igetw(&section_version,f))
12961 {
12962 return 0;
12963 }
12964 if(!p_igetw(&section_cversion,f))
12965 {
12966 return 0;
12967 }
12968
12969 if ( zversion > ZELDA_VERSION )
12970 {
12971 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12972 return 0;
12973 }
12974
12975 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12976 {
12977 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12978 return 0;
12979
12980 }
12981 else
12982 {
12983 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12984 }
12985
12986 int32_t index = 0;
12987 int32_t count = 0;
12988
12989 //tile id
12990 if(!p_igetl(&index,f))
12991 {
12992 return 0;
12993 }
12994 if(start > -1) index = start;
12995 // al_trace("Reading combo: index(%d)\n", index);
12996
12997 //tile count
12998 if(!p_igetl(&count,f))
12999 {
13000 return 0;
13001 }
13002 // al_trace("Reading combo: count(%d)\n", count);
13003 reset_combo_animations();
13004 reset_combo_animations2();
13005
13006 if(section_version < 33)
13007 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13008
13009 newcombo temp_combo;
13010 size_t end = index+count;
13011 for ( size_t q = index; q < end; q++ )
13012 {
13013 auto ret = readcombo_loop(f,section_version,temp_combo);
13014 if(ret) return 0;
13015
13016 if ( !(skip && q-1 < skip) )
13017 {
13018 if ( !nooverwrite || combobuf[q].is_blank() )
13019 {
13020 combobuf[q] = temp_combo;
13021 }
13022 }
13023 }
13024
13025 return 1;
13026 }
13027 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13028 {
13029 return readcombofile(f,skip,nooverwrite,start);
13030 }
13031 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13032 {
13033 dword section_version=V_COMBOS;
13034 dword section_cversion=CV_COMBOS;
13035 int32_t zversion = ZELDA_VERSION;
13036 int32_t zbuild = VERSION_BUILD;
13037
13038 if(!p_iputl(zversion,f))
13039 {
13040 return 0;
13041 }
13042 if(!p_iputl(zbuild,f))
13043 {
13044 return 0;
13045 }
13046 if(!p_iputw(section_version,f))
13047 {
13048 return 0;
13049 }
13050
13051 if(!p_iputw(section_cversion,f))
13052 {
13053 return 0;
13054 }
13055
13056 //start tile id
13057 if(!p_iputl(index,f))
13058 {
13059 return 0;
13060 }
13061
13062 //count
13063 if(!p_iputl(count,f))
13064 {
13065 return 0;
13066 }
13067 reset_combo_animations();
13068 reset_combo_animations2();
13069 size_t end = index+count;
13070 for(size_t q = index; q < end; ++q)
13071 {
13072 if(writecombo_loop(f, section_version, combobuf[q]))
13073 return 0;
13074 }
13075
13076 return 1;
13077
13078 }
13079
13080 //.ZALIAS
13081
13082
13083 //.ZALIAS
13084
13085 int32_t readcomboaliasfile(PACKFILE *f)
13086 {
13087 dword section_version=0;
13088 dword section_cversion=0;
13089 int32_t zversion = 0;
13090 int32_t zbuild = 0;
13091 word tempword = 0;
13092
13093 if(!p_igetl(&zversion,f))
13094 {
13095 return 0;
13096 }
13097 if(!p_igetl(&zbuild,f))
13098 {
13099 return 0;
13100 }
13101 if(!p_igetw(&section_version,f))
13102 {
13103 return 0;
13104 }
13105 if(!p_igetw(&section_cversion,f))
13106 {
13107 return 0;
13108 }
13109 al_trace("readoneweapon section_version: %d\n", section_version);
13110 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13111
13112 if ( zversion > ZELDA_VERSION )
13113 {
13114 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13115 return 0;
13116 }
13117
13118 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13119 {
13120 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13121 return 0;
13122
13123 }
13124 else
13125 {
13126 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13127 }
13128
13129 int32_t index = 0;
13130 int32_t count = 0;
13131 int32_t count2 = 0;
13132 byte tempcset = 0;
13133
13134 //tile id
13135 if(!p_igetl(&index,f))
13136 {
13137 return 0;
13138 }
13139 al_trace("Reading combo: index(%d)\n", index);
13140
13141 //tile count
13142 if(!p_igetl(&count,f))
13143 {
13144 return 0;
13145 }
13146 al_trace("Reading combo: count(%d)\n", count);
13147
13148 combo_alias temp_alias;
13149 memset(&temp_alias, 0, sizeof(temp_alias));
13150
13151 for ( int32_t tilect = 0; tilect < count; tilect++ )
13152 {
13153 memset(&temp_alias, 0, sizeof(temp_alias));
13154 if(!p_igetw(&temp_alias.combo,f))
13155 {
13156 return 0;
13157 }
13158
13159 if(!p_getc(&temp_alias.cset,f))
13160 {
13161 return 0;
13162 }
13163
13164
13165
13166 if(!p_igetl(&count2,f))
13167 {
13168 return 0;
13169 }
13170 al_trace("Read, Combo alias count is: %d\n", count2);
13171 if(!p_getc(&temp_alias.width,f))
13172 {
13173 return 0;
13174 }
13175
13176 if(!p_getc(&temp_alias.height,f))
13177 {
13178 return 0;
13179 }
13180
13181 if(!p_getc(&temp_alias.layermask,f))
13182 {
13183 return 0;
13184 }
13185 //These values are flexible, and may differ in size, so we delete them
13186 //and recreate them at the correct size on the pointer.
13187 temp_alias.combos.clear();
13188 temp_alias.csets.clear();
13189 for(int32_t k=0; k<count2; k++)
13190 {
13191 if(!p_igetw(&tempword,f))
13192 {
13193 return 0;
13194 }
13195 else
13196 {
13197
13198
13199 temp_alias.combos[k] = tempword;
13200 }
13201 }
13202
13203 for(int32_t k=0; k<count2; k++)
13204 {
13205 if(!p_getc(&tempcset,f))
13206 //if(!p_getc(&temp_alias.csets[k],f))
13207 {
13208 return 0;
13209 }
13210 else
13211 {
13212
13213 temp_alias.csets[k] = tempcset;
13214 }
13215 }
13216 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13217 }
13218
13219 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13220
13221
13222 return 1;
13223
13224 }
13225
13226 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13227 {
13228 dword section_version=0;
13229 dword section_cversion=0;
13230 int32_t zversion = 0;
13231 int32_t zbuild = 0;
13232
13233 if(!p_igetl(&zversion,f))
13234 {
13235 return 0;
13236 }
13237 if(!p_igetl(&zbuild,f))
13238 {
13239 return 0;
13240 }
13241 if(!p_igetw(&section_version,f))
13242 {
13243 return 0;
13244 }
13245 if(!p_igetw(&section_cversion,f))
13246 {
13247 return 0;
13248 }
13249 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13250 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13251
13252 if ( zversion > ZELDA_VERSION )
13253 {
13254 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13255 return 0;
13256 }
13257 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13258 {
13259 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13260 return 0;
13261
13262 }
13263 else
13264 {
13265 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13266 }
13267
13268 int32_t index = 0;
13269 int32_t count = 0;
13270 int32_t count2 = 0;
13271 byte tempcset = 0;
13272 word tempword = 0;
13273
13274
13275 //tile id
13276 if(!p_igetl(&index,f))
13277 {
13278 return 0;
13279 }
13280 al_trace("Reading tile: index(%d)\n", index);
13281
13282 //tile count
13283 if(!p_igetl(&count,f))
13284 {
13285 return 0;
13286 }
13287 al_trace("Reading tile: count(%d)\n", count);
13288
13289
13290 combo_alias temp_alias;
13291 memset(&temp_alias, 0, sizeof(temp_alias));
13292
13293 for ( int32_t tilect = 0; tilect < count; tilect++ )
13294 {
13295 memset(&temp_alias, 0, sizeof(temp_alias));
13296 if(!p_igetw(&temp_alias.combo,f))
13297 {
13298 return 0;
13299 }
13300
13301 if(!p_getc(&temp_alias.cset,f))
13302 {
13303 return 0;
13304 }
13305
13306 int32_t count2 = 0;
13307
13308 if(!p_igetl(&count2,f))
13309 {
13310 return 0;
13311 }
13312
13313 if(!p_getc(&temp_alias.width,f))
13314 {
13315 return 0;
13316 }
13317
13318 if(!p_getc(&temp_alias.height,f))
13319 {
13320 return 0;
13321 }
13322
13323 if(!p_getc(&temp_alias.layermask,f))
13324 {
13325 return 0;
13326 }
13327 //These values are flexible, and may differ in size, so we delete them
13328 //and recreate them at the correct size on the pointer.
13329 temp_alias.combos.clear();
13330 temp_alias.csets.clear();
13331
13332 for(int32_t k=0; k<count2; k++)
13333 {
13334 if(!p_igetw(&tempword,f))
13335 {
13336 return 0;
13337 }
13338 else
13339 {
13340 temp_alias.combos[k] = tempword;
13341 }
13342 }
13343
13344 for(int32_t k=0; k<count2; k++)
13345 {
13346 if(!p_getc(&tempcset,f))
13347 {
13348 return 0;
13349 }
13350 else
13351 {
13352 temp_alias.csets[k] = tempcset;
13353 }
13354 }
13355
13356 if ( start+(tilect) < MAXCOMBOALIASES )
13357 {
13358 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13359 }
13360 }
13361 return 1;
13362 }
13363 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13364 {
13365 al_trace("Running writecomboaliasfile\n");
13366 dword section_version=V_COMBOALIASES;
13367 dword section_cversion=CV_COMBOALIASES;
13368 int32_t zversion = ZELDA_VERSION;
13369 int32_t zbuild = VERSION_BUILD;
13370
13371 if(!p_iputl(zversion,f))
13372 {
13373 return 0;
13374 }
13375 if(!p_iputl(zbuild,f))
13376 {
13377 return 0;
13378 }
13379 if(!p_iputw(section_version,f))
13380 {
13381 return 0;
13382 }
13383
13384 if(!p_iputw(section_cversion,f))
13385 {
13386 return 0;
13387 }
13388
13389 //start tile id
13390 if(!p_iputl(index,f))
13391 {
13392 return 0;
13393 }
13394
13395 //count
13396 if(!p_iputl(count,f))
13397 {
13398 return 0;
13399 }
13400
13401 for ( int32_t tilect = 0; tilect < count; tilect++ )
13402 {
13403
13404 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13405 {
13406 return 0;
13407 }
13408
13409 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13410 {
13411 return 0;
13412 }
13413
13414 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13415
13416 if(!p_iputl(count2,f))
13417 {
13418 return 0;
13419 }
13420 al_trace("Write`, Combo alias count is: %d\n", count2);
13421
13422 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13423 {
13424 return 0;
13425 }
13426
13427 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13428 {
13429 return 0;
13430 }
13431
13432 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13433 {
13434 return 0;
13435 }
13436
13437 for(int32_t k=0; k<count2; k++)
13438 {
13439 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13440 {
13441 return 0;
13442 }
13443 }
13444
13445 for(int32_t k=0; k<count2; k++)
13446 {
13447 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13448 {
13449 return 0;
13450 }
13451 }
13452 }
13453
13454 return 1;
13455
13456 }
13457